Merge pull request #389 from adafruit/add-ch32v20x

Add ch32v20x
This commit is contained in:
Ha Thach 2024-06-04 23:41:13 +07:00 committed by GitHub
commit faab9f4a74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 3717 additions and 788 deletions

View file

@ -9,6 +9,8 @@ on:
- 'src/**'
- '.github/actions/**'
- '.github/workflows/build.yml'
- '.github/workflows/build_util.yml'
- '.github/workflows/build_ghostfat.yml'
pull_request:
branches: [ master ]
paths:
@ -18,6 +20,8 @@ on:
- 'src/**'
- '.github/actions/**'
- '.github/workflows/build.yml'
- '.github/workflows/build_util.yml'
- '.github/workflows/build_ghostfat.yml'
repository_dispatch:
release:
types:
@ -57,7 +61,7 @@ jobs:
matrix:
port:
# Alphabetical order
#- 'kinetis_k32l2' skip since self-update is not implemented
- 'kinetis_k32l2'
- 'lpc55'
- 'mimxrt10xx'
- 'stm32f3'
@ -73,6 +77,7 @@ jobs:
# Build ESP
# ---------------------------------------
esp:
#if: false
needs: set-matrix
uses: ./.github/workflows/build_util.yml
with:
@ -82,51 +87,30 @@ jobs:
toolchain: 'esp-idf'
toolchain_url: 'v5.1.1'
# ---------------------------------------
# Build RISC-V
# ---------------------------------------
riscv:
needs: set-matrix
uses: ./.github/workflows/build_util.yml
strategy:
fail-fast: false
matrix:
port:
# Alphabetical order
- 'ch32v20x'
with:
port: ${{ matrix.port }}
boards: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.port].board) }}
build-system: 'make'
toolchain: 'riscv-gcc'
toolchain_url: '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'
# ---------------------------------------
# Unit testing with ghostfat
# ---------------------------------------
ghostfat:
needs: set-matrix
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
board: ${{ fromJSON(needs.set-matrix.outputs.json)['test_ghostfat'].board }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build
run: |
make -C ports/test_ghostfat/ BOARD=${{ matrix.board }} all
- name: Decompress known good filesystem image
run: |
# copy
cp ./boards/${{ matrix.board }}/knowngood.img.gz.gz ./_build/${{ matrix.board }}/
# NOTE: test_huge's knowngood.img file starts as 1.5 GiB
# Compressing once with GZip results gives 85 MiB
# Compressing it a second time gives 10 MiB ...
# Therefore, store known good images double-compressed...
gzip --decompress ./_build/${{ matrix.board }}/knowngood.img.gz.gz
gzip --decompress ./_build/${{ matrix.board }}/knowngood.img.gz
working-directory: ports/test_ghostfat
- name: Execute native self-test
run: |
chmod +x ./tinyuf2-${{ matrix.board }}.elf
./tinyuf2-${{ matrix.board }}.elf
# Compress (double) newly generated self-test images
mv ghostfat.img ghostfat_${{ matrix.board }}.img
gzip --keep ghostfat_${{ matrix.board }}.img
gzip --keep --force --best ghostfat_${{ matrix.board }}.img.gz
working-directory: ports/test_ghostfat/_build/${{ matrix.board }}
- name: Save newly generated self-test images as CI artifacts
uses: actions/upload-artifact@v3
with:
name: ghostfat_selftest_images
path: ./ports/test_ghostfat/_build/${{ matrix.board }}/ghostfat_${{ matrix.board }}.img.gz.gz
uses: ./.github/workflows/build_ghostfat.yml
with:
boards: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['test_ghostfat'].board) }}

View file

@ -37,7 +37,7 @@ jobs:
board:
# Alphabetical order by family
- 'metro_m7_1011'
- 'stm32f303disco'
# - 'stm32f303disco' # overflows flash
- 'stm32f411ve_discovery'
steps:

51
.github/workflows/build_ghostfat.yml vendored Normal file
View file

@ -0,0 +1,51 @@
name: Testing ghostfat
on:
workflow_call:
inputs:
boards:
required: true
type: string
jobs:
board:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
board: ${{ fromJSON(inputs.boards) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build
run: |
make -C ports/test_ghostfat/ BOARD=${{ matrix.board }} all
- name: Decompress known good filesystem image
run: |
# NOTE: test_huge's knowngood.img file starts as 1.5 GiB
# Compressing once with GZip results gives 85 MiB
# Compressing it a second time gives 10 MiB ...
# Therefore, store known good images double-compressed...
cp ./boards/${{ matrix.board }}/knowngood.img.gz.gz ./_build/${{ matrix.board }}/
gzip --decompress ./_build/${{ matrix.board }}/knowngood.img.gz.gz
gzip --decompress ./_build/${{ matrix.board }}/knowngood.img.gz
working-directory: ports/test_ghostfat
- name: Execute native self-test
run: |
chmod +x ./tinyuf2-${{ matrix.board }}.elf
./tinyuf2-${{ matrix.board }}.elf
# Compress (double) newly generated self-test images
mv ghostfat.img ghostfat_${{ matrix.board }}.img
gzip --keep ghostfat_${{ matrix.board }}.img
gzip --keep --force --best ghostfat_${{ matrix.board }}.img.gz
working-directory: ports/test_ghostfat/_build/${{ matrix.board }}
- name: Save newly generated self-test images as CI artifacts
uses: actions/upload-artifact@v3
with:
name: ghostfat_selftest_images
path: ./ports/test_ghostfat/_build/${{ matrix.board }}/ghostfat_${{ matrix.board }}.img.gz.gz

View file

@ -50,7 +50,9 @@ jobs:
if: inputs.toolchain != 'esp-idf'
run: |
make -C ports/${{ inputs.port }} BOARD=${{ matrix.board }} all self-update copy-artifact
for app in ports/${{ inputs.port }}/apps/*/; do if [ $app != 'apps/self_update/' ]; then make -C $app BOARD=${{ matrix.board }} all; fi done
if [ -d "ports/${{ inputs.port }}/apps" ]; then
for app in ports/${{ inputs.port }}/apps/*/; do if [ $app != 'apps/self_update/' ]; then make -C $app BOARD=${{ matrix.board }} all; fi done
fi
- name: Build using ESP-IDF docker
if: inputs.toolchain == 'esp-idf'

View file

@ -8,13 +8,13 @@ TOP = Path(__file__).parent.parent.parent.resolve()
def set_matrix_json():
ports_dir = Path(TOP / 'ports')
matrix = {}
for p in ports_dir.iterdir():
for p in sorted(ports_dir.iterdir()):
if p.is_dir() and p.name != 'template_port':
matrix[p.name] = {}
boards_dir = ports_dir / p / 'boards'
if boards_dir.exists():
matrix[p.name]['board'] = []
for b in boards_dir.iterdir():
for b in sorted(boards_dir.iterdir()):
if b.is_dir():
matrix[p.name]['board'].append(b.name)
print(json.dumps(matrix))

View file

@ -24,8 +24,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "board_api.h"
@ -33,34 +31,25 @@
* writing the erase magic and reset to let bootloader do its work
*/
#ifndef DBL_TAP_REG
// defined by linker script
extern uint32_t _board_dfu_dbl_tap[];
#define DBL_TAP_REG _board_dfu_dbl_tap[0]
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
int main(void)
{
int main(void) {
board_init();
printf("Erase Application Firmware\r\n");
// set magic then reset
DBL_TAP_REG = DBL_TAP_MAGIC_ERASE_APP;
TINYUF2_DBL_TAP_REG = DBL_TAP_MAGIC_ERASE_APP;
board_reset();
while(1)
{
while (1) {
// nothing to do
}
}
void board_timer_handler(void)
{
void board_timer_handler(void) {
}
@ -75,8 +64,7 @@ void board_timer_handler(void)
#include "SEGGER_RTT.h"
#endif
__attribute__ ((used)) int _write (int fhdl, const void *buf, size_t count)
{
__attribute__ ((used)) int _write(int fhdl, const void* buf, size_t count) {
(void) fhdl;
#if defined(LOGGER_RTT)

View file

@ -0,0 +1,21 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mcpu=arm1176jzf-s
-ffreestanding
)
# set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=arm1176jzf-s
-mfpu=none
-mfloat-abi=soft
-ffreestanding
)
#set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
endif ()

View file

@ -0,0 +1,21 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mcpu=arm926ej-s
-ffreestanding
)
# set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=arm926ej-s
-mfpu=none
-mfloat-abi=soft
-ffreestanding
)
#set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
endif ()

View file

@ -0,0 +1,17 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mcpu=cortex-a53
)
# set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-a53
)
#set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
endif ()

View file

@ -0,0 +1,17 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mcpu=cortex-a72
)
# set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-a72
)
#set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
endif ()

22
cmake/cpu/cortex-m0.cmake Normal file
View file

@ -0,0 +1,22 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m0plus
-mfloat-abi=soft
)
set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m0
)
set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m0
)
set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,22 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m0plus
-mfloat-abi=soft
)
set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m0plus
)
set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m0
)
set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,22 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m23
-mfloat-abi=soft
)
set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m23
)
set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m23
)
set(FREERTOS_PORT IAR_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "")
endif ()

21
cmake/cpu/cortex-m3.cmake Normal file
View file

@ -0,0 +1,21 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m3
)
set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m3
)
set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m3
)
set(FREERTOS_PORT IAR_ARM_CM3 CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,18 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m33+nodsp
-mfloat-abi=soft
)
set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
message(FATAL_ERROR "Clang is not supported for this target")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m33+nodsp
)
set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,25 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m33
-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
-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
--fpu VFPv5-SP
)
set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
endif ()

View file

@ -1,23 +1,32 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
)
if (NOT DEFINED FREERTOS_PORT)
set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "")
endif ()
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m4
--fpu VFPv4
)
if (NOT DEFINED FREERTOS_PORT)
set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "")
endif ()
endif ()
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
)
if (NOT DEFINED FREERTOS_PORT)
set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "")
endif ()
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m4
-mfpu=fpv4-sp-d16
)
if (NOT DEFINED FREERTOS_PORT)
set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "")
endif ()
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m4
--fpu VFPv4_sp
)
if (NOT DEFINED FREERTOS_PORT)
set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "")
endif ()
endif ()

View file

@ -0,0 +1,25 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m7
-mfloat-abi=hard
-mfpu=fpv5-sp-d16
)
set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m7
-mfpu=fpv5-sp-d16
)
set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m7
--fpu VFPv5_sp
)
set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "")
endif ()

View file

@ -1,19 +1,25 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m7
-mfloat-abi=hard
-mfpu=fpv5-d16
)
set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m7
--fpu VFPv5_D16
)
set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "")
endif ()
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-mthumb
-mcpu=cortex-m7
-mfloat-abi=hard
-mfpu=fpv5-d16
)
set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
--target=arm-none-eabi
-mcpu=cortex-m7
-mfpu=fpv5-d16
)
set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
set(TOOLCHAIN_COMMON_FLAGS
--cpu cortex-m7
--fpu VFPv5_D16
)
set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "")
endif ()

10
cmake/cpu/msp430.cmake Normal file
View file

@ -0,0 +1,10 @@
if (TOOLCHAIN STREQUAL "gcc")
set(FREERTOS_PORT GCC_MSP430F449 CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
message(FATAL_ERROR "Clang is not supported for this target")
elseif (TOOLCHAIN STREQUAL "iar")
set(FREERTOS_PORT IAR_MSP430 CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,19 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-march=rv32i_zicsr
-mabi=ilp32
)
set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
-march=rv32i_zicsr
-mabi=ilp32
)
set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
set(FREERTOS_PORT IAR_RISC_V CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,18 @@
if (TOOLCHAIN STREQUAL "gcc")
set(TOOLCHAIN_COMMON_FLAGS
-march=rv32imac_zicsr
-mabi=ilp32
)
set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "clang")
set(TOOLCHAIN_COMMON_FLAGS
-march=rv32imac_zicsr
-mabi=ilp32
)
set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "")
elseif (TOOLCHAIN STREQUAL "iar")
message(FATAL_ERROR "IAR not supported")
set(FREERTOS_PORT IAR_RISC_V CACHE INTERNAL "")
endif ()

View file

@ -0,0 +1,21 @@
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "aarch64-none-elf-gcc")
endif ()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER "aarch64-none-elf-g++")
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_SIZE "aarch64-none-elf-size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "aarch64-none-elf-objcopy" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "aarch64-none-elf-objdump" CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if (IS_IN_TRY_COMPILE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
cmake_print_variables(CMAKE_C_LINK_FLAGS)
endif ()

View file

@ -0,0 +1,21 @@
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "clang")
endif ()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER "clang++")
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_SIZE "llvm-size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "llvm-objcopy" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "llvm-objdump" CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if (IS_IN_TRY_COMPILE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
cmake_print_variables(CMAKE_C_LINK_FLAGS)
endif ()

View file

@ -1,46 +1,21 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
set(CMAKE_CXX_COMPILER "arm-none-eabi-g++")
set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc")
set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "")
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
# Look for includes and libraries only in the target system prefix.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# pass TOOLCHAIN_CPU to
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR)
include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake)
# enable all possible warnings for building examples
list(APPEND TOOLCHAIN_COMMON_FLAGS
-fdata-sections
-ffunction-sections
-fsingle-precision-constant
-fno-strict-aliasing
)
set(TOOLCHAIN_EXE_LINKER_FLAGS
-Wl,--print-memory-usage
-Wl,--gc-sections
#-Wl,--cref
)
include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake)
# try_compile is cmake test compiling its own example,
# pass -nostdlib to skip stdlib linking
get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if (IS_IN_TRY_COMPILE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
endif ()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
endif ()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER "arm-none-eabi-g++")
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if (IS_IN_TRY_COMPILE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
cmake_print_variables(CMAKE_C_LINK_FLAGS)
endif ()

View file

@ -0,0 +1,17 @@
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "iccarm")
endif()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER "iccarm")
endif()
if (NOT DEFINED CMAKE_ASM_COMPILER)
set(CMAKE_ASM_COMPILER "iasmarm")
endif()
set(CMAKE_SIZE "size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "iefdumparm" CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)

View file

@ -0,0 +1,64 @@
include(CMakePrintHelpers)
# ----------------------------------------------------------------------------
# Common
# ----------------------------------------------------------------------------
set(CMAKE_SYSTEM_NAME Generic)
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
# Look for includes and libraries only in the target system prefix.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# pass TOOLCHAIN_CPU to
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR)
include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake)
# ----------------------------------------------------------------------------
# Compile flags
# ----------------------------------------------------------------------------
if (TOOLCHAIN STREQUAL "gcc")
list(APPEND TOOLCHAIN_COMMON_FLAGS
-fdata-sections
-ffunction-sections
-fsingle-precision-constant
-fno-strict-aliasing
)
list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
-Wl,--print-memory-usage
-Wl,--gc-sections
-Wl,--cref
)
elseif (TOOLCHAIN STREQUAL "iar")
#list(APPEND TOOLCHAIN_COMMON_FLAGS)
list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
--diag_suppress=Li065
)
elseif (TOOLCHAIN STREQUAL "clang")
list(APPEND TOOLCHAIN_COMMON_FLAGS
-fdata-sections
-ffunction-sections
-fno-strict-aliasing
)
list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS
-Wl,--print-memory-usage
-Wl,--gc-sections
-Wl,--cref
)
endif ()
# join the toolchain flags into a single string
list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS)
foreach (LANG IN ITEMS C CXX ASM)
set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS})
# optimization flags for LOG, LOGGER ?
#set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os")
#set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0")
endforeach ()
# Linker
list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT)

View file

@ -0,0 +1,15 @@
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "msp430-elf-gcc")
endif ()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER "msp430-elf-g++")
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_SIZE "msp430-elf-size" CACHE FILEPATH "")
set(CMAKE_OBJCOPY "msp430-elf-objcopy" CACHE FILEPATH "")
set(CMAKE_OBJDUMP "msp430-elf-objdump" CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)

View file

@ -0,0 +1,30 @@
# default Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
if (NOT DEFINED CROSS_COMPILE)
set(CROSS_COMPILE "riscv-none-elf-")
endif ()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
endif ()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
endif ()
if (NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_SIZE ${CROSS_COMPILE}size CACHE FILEPATH "")
set(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy CACHE FILEPATH "")
set(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump CACHE FILEPATH "")
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if (IS_IN_TRY_COMPILE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib")
cmake_print_variables(CMAKE_C_LINK_FLAGS)
endif ()

View file

@ -1,12 +0,0 @@
include(CMakePrintHelpers)
# join the toolchain flags into a single string
list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS)
foreach (LANG IN ITEMS C CXX ASM)
set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS})
#cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT)
endforeach ()
# Linker
list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT)

View file

@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_LIST_DIR}/../family_support.cmake)
project(tinyuf2 C ASM)
set(CMAKE_EXECUTABLE_SUFFIX .elf)
#------------------------------------
# TinyUF2
#------------------------------------
add_executable(tinyuf2
boards.c
)
target_link_options(tinyuf2 PUBLIC
"LINKER:--script=${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}_boot.ld"
)
family_configure_tinyuf2(tinyuf2 OPT_MCU_CH32V20X)
target_sources(tinyuf2-tinyusb PUBLIC
${TOP}/lib/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/lib/tinyusb/src/portable/wch/dcd_ch32_usbfs.c
)
family_flash_openocd_wch(tinyuf2)
#------------------------------------
# Application (e.g self update)
#------------------------------------
#add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/apps/self_update)

24
ports/ch32v20x/Makefile Normal file
View file

@ -0,0 +1,24 @@
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = tinyusb
include ../make.mk
include port.mk
include ../rules.mk
#------------------------------------------
# Self-update
#------------------------------------------
# directory containing Makefile for building update app
SELF_DIR = apps/self_update
#$(SELF_DIR)/bootloader_bin.c: $(BUILD)/$(OUTNAME).bin
# $(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o $@
#
## remove bootloader_bin.c at the end to force re-generate each time
#self-update: $(SELF_DIR)/bootloader_bin.c
# make -C $(SELF_DIR) BOARD=$(BOARD) LOG=$(LOG) LOGGER=$(LOGGER) self-update
# @rm -f $^
self-update:
@echo "not implemented yet"

297
ports/ch32v20x/boards.c Normal file
View file

@ -0,0 +1,297 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ha Thach for Adafruit Industries
*
* 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 "ch32v20x.h"
#include "board_api.h"
#ifndef BUILD_NO_TINYUSB
#include "tusb.h"
#endif
#define CH32_UUID ((volatile uint32_t *) 0x1FFFF7E8UL)
#define BOARD_PAGE_SIZE 0x800
#define FLASH_ADDR_PHY_BASE 0x08000000UL
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
// convert to zero-based address
#define ADDR_BASE0(_addr) ((_addr) & ~FLASH_ADDR_PHY_BASE)
// convert to absolute address
#define ADDR_ABS(_addr) ((_addr) | FLASH_ADDR_PHY_BASE)
uint32_t SysTick_Config(uint32_t ticks) {
NVIC_EnableIRQ(SysTicK_IRQn);
SysTick->CTLR = 0;
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = ticks - 1;
SysTick->CTLR = 0xF;
return 0;
}
void board_init(void) {
__disable_irq();
// double tap use backup register: enable PWR and BKP clock, and BKP write enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);
PWR->CTLR |= PWR_CTLR_DBP;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = LED_PIN,
.GPIO_Mode = GPIO_Mode_Out_OD,
.GPIO_Speed = GPIO_Speed_50MHz,
};
GPIO_Init(LED_PORT, &GPIO_InitStructure);
#if CFG_TUSB_DEBUG || TUF2_LOG
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);
#endif
__enable_irq();
}
void board_teardown(void) {
}
void board_dfu_init(void) {
__disable_irq();
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);
#if CFG_TUD_WCH_USBIP_USBFS
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS
#endif
#if CFG_TUD_WCH_USBIP_FSDEV
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV
#endif
__enable_irq();
}
void board_reset(void) {
NVIC_SystemReset();
}
void board_dfu_complete(void) {
// Mostly reset
NVIC_SystemReset();
}
bool board_app_valid(void) {
uint32_t app_start_contents = *((volatile uint32_t const*) ADDR_ABS(BOARD_FLASH_APP_START));
TUF2_LOG1_HEX(app_start_contents);
// for ch32 after erased the flash value is 0xe339e339 (mentioned in RM) instead of 0xffffffff
return app_start_contents != 0xe339e339;
}
// Jump to application code
void board_app_jump(void) {
TUF2_LOG2("Jump to app\r\n");
board_timer_stop();
asm volatile("j __flash_boot_size");
}
uint8_t board_usb_get_serial(uint8_t serial_id[16]) {
uint8_t const len = 12;
uint32_t* serial_id32 = (uint32_t*) (uintptr_t) serial_id;
serial_id32[0] = CH32_UUID[0];
serial_id32[1] = CH32_UUID[1];
serial_id32[2] = CH32_UUID[2];
return len;
}
//--------------------------------------------------------------------+
// LED pattern
//--------------------------------------------------------------------+
void board_led_write(uint32_t state) {
GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
}
void board_rgb_write(uint8_t const rgb[]) {
(void) rgb;
}
//--------------------------------------------------------------------+
// Timer
//--------------------------------------------------------------------+
void board_timer_start(uint32_t ms) {
SysTick_Config( (SystemCoreClock/1000) * ms );
}
void board_timer_stop(void) {
SysTick->CTLR = 0;
}
__attribute__((interrupt)) __attribute__((used))
void SysTick_Handler(void) {
SysTick->SR = 0;
board_timer_handler();
}
int board_uart_write(void const* buf, int len) {
#if CFG_TUSB_DEBUG || TUF2_LOG
const char *bufc = (const char *) buf;
for (int i = 0; i < len; i++) {
USART_SendData(USART1, *bufc++);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
//--------------------------------------------------------------------+
// Flash
//--------------------------------------------------------------------+
void board_flash_init(void) {
// nothing to do
}
uint32_t board_flash_size(void) {
return BOARD_FLASH_SIZE;
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
memcpy(buffer, (void*) addr, len);
}
void board_flash_flush(void) {
// nothing to do
}
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
TUF2_ASSERT(len == 256);
addr = ADDR_ABS(addr);
FLASH_Unlock_Fast();
FLASH_ErasePage_Fast(addr);
FLASH_ProgramPage_Fast(addr, (uint32_t*) (uintptr_t ) data);
FLASH_Lock_Fast();
// verify contents
if (memcmp((void*) addr, data, len) != 0) {
TUF2_LOG1("Failed to write\r\n");
}
return true;
}
void board_flash_erase_app(void) {
// TODO implement later
}
bool board_flash_protect_bootloader(bool protect) {
// TODO implement later
(void) protect;
return false;
}
#ifdef TINYUF2_SELF_UPDATE
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len) {
(void) bootloader_bin;
(void) bootloader_len;
}
#endif
//--------------------------------------------------------------------+
// USB Interrupt Handler
//--------------------------------------------------------------------+
#ifndef BUILD_NO_TINYUSB
// USBFS
__attribute__((interrupt)) __attribute__((used))
void USBFS_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used))
void USBFSWakeUp_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
// USBD (fsdev)
__attribute__((interrupt)) __attribute__((used))
void USB_LP_CAN1_RX0_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used))
void USB_HP_CAN1_TX_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used))
void USBWakeUp_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
#endif

View file

@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ha Thach for Adafruit Industries
* Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -22,52 +22,29 @@
* THE SOFTWARE.
*/
#include "board_api.h"
#include "tusb.h" // for logging
#ifndef BOARDS_H_
#define BOARDS_H_
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
void board_flash_init(void)
{
}
uint32_t board_flash_size(void)
{
return 0;
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len)
{
(void) addr; (void) buffer; (void) len;
}
void board_flash_flush(void)
{
}
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
{
(void) addr; (void) data; (void) len;
}
void board_flash_erase_app(void)
{
// TODO implement later
}
bool board_flash_protect_bootloader(bool protect)
{
// TODO implement later
(void) protect;
return false;
}
#ifdef TINYUF2_SELF_UPDATE
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
(void) bootloader_bin;
(void) bootloader_len;
}
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
#include "board.h"
#define TINYUF2_DBL_TAP_DFU 1
#define TINYUF2_DBL_TAP_REG BKP->DATAR10
#define TINYUF2_DBL_TAP_REG_SIZE 16
// symbol from linker
extern uint32_t __flash_size[];
extern uint32_t __flash_boot_size[];
#define BOARD_FLASH_SIZE ((uint32_t) __flash_size)
#define BOARD_FLASH_APP_START ((uint32_t) __flash_boot_size)
#ifdef __cplusplus
}
#endif
#endif /* BOARDS_H_ */

View file

@ -0,0 +1,6 @@
set(MCU_VARIANT D6)
set(LD_FLASH_SIZE 64K)
set(LD_RAM_SIZE 20K)
function(update_board TARGET)
endfunction()

View file

@ -0,0 +1,65 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ha Thach for Adafruit Industries
*
* 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 BOARD_H_
#define BOARD_H_
//--------------------------------------------------------------------+
// Button
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// LED
//--------------------------------------------------------------------+
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_15
#define LED_STATE_ON 1
//--------------------------------------------------------------------+
// USB UF2
//--------------------------------------------------------------------+
#define USB_VID 0xcafe
#define USB_PID 0xbabe
#define USB_MANUFACTURER "Adafruit"
#define USB_PRODUCT "Dummy"
#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT
#define UF2_BOARD_ID "Dummy"
#define UF2_VOLUME_LABEL "CH32V2BOOT"
#define UF2_INDEX_URL "https://www.adafruit.com"
//--------------------------------------------------------------------+
// UART
//--------------------------------------------------------------------+
//#define UART_DEV USART3
//#define UART_CLOCK_ENABLE __HAL_RCC_USART3_CLK_ENABLE
//#define UART_GPIO_PORT GPIOB
//#define UART_GPIO_AF GPIO_AF7_USART3
//#define UART_TX_PIN GPIO_PIN_10
//#define UART_RX_PIN GPIO_PIN_11
#endif

View file

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

View file

@ -0,0 +1,36 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* 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 __CH32V20x_CONF_H
#define __CH32V20x_CONF_H
#include "ch32v20x_adc.h"
#include "ch32v20x_bkp.h"
#include "ch32v20x_can.h"
#include "ch32v20x_crc.h"
#include "ch32v20x_dbgmcu.h"
#include "ch32v20x_dma.h"
#include "ch32v20x_exti.h"
#include "ch32v20x_flash.h"
#include "ch32v20x_gpio.h"
#include "ch32v20x_i2c.h"
#include "ch32v20x_iwdg.h"
#include "ch32v20x_pwr.h"
#include "ch32v20x_rcc.h"
#include "ch32v20x_rtc.h"
#include "ch32v20x_spi.h"
#include "ch32v20x_tim.h"
#include "ch32v20x_usart.h"
#include "ch32v20x_wwdg.h"
#include "ch32v20x_it.h"
#include "ch32v20x_misc.h"
#endif /* __CH32V20x_CONF_H */

View file

@ -0,0 +1,15 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* 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 __CH32V20x_IT_H
#define __CH32V20x_IT_H
#endif /* __CH32V20x_IT_H */

572
ports/ch32v20x/core_riscv.h Normal file
View file

@ -0,0 +1,572 @@
/********************************** (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

@ -0,0 +1,84 @@
include_guard()
set(UF2_FAMILY_ID 0x699b62ec)
set(CH32_FAMILY ch32v20x)
set(SDK_DIR ${TOP}/lib/mcu/wch/${CH32_FAMILY})
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# enable LTO
#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
#------------------------------------
# BOARD_TARGET
#------------------------------------
# used by all executable targets
# Port0 use FSDev, Port1 use USBFS
if (NOT DEFINED USBPORT)
set(USBPORT 0)
endif()
function(family_add_board_target BOARD_TARGET)
if (TARGET ${BOARD_TARGET})
return()
endif ()
if (NOT DEFINED STARTUP_FILE_GNU)
set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S)
endif ()
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
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
${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}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CH32V20x_${MCU_VARIANT}
)
if (USBPORT EQUAL 0)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CFG_TUD_WCH_USBIP_FSDEV=1
)
elseif (USBPORT EQUAL 1)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CFG_TUD_WCH_USBIP_USBFS=1
)
else()
message(FATAL_ERROR "Invalid PORT ${USBPORT}")
endif()
update_board(${BOARD_TARGET})
target_compile_definitions(${BOARD_TARGET} PUBLIC
#CFG_TUSB_MCU=OPT_MCU_CH32V20X
BOARD_UF2_FAMILY_ID=${UF2_FAMILY_ID}
)
target_compile_options(${BOARD_TARGET} PUBLIC
-mcmodel=medany
)
target_link_options(${BOARD_TARGET} PUBLIC
-Wl,--defsym=__flash_size=${LD_FLASH_SIZE}
-Wl,--defsym=__ram_size=${LD_RAM_SIZE}
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
endfunction()

View file

@ -0,0 +1,168 @@
/* Define default values if not already defined */
__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K;
__flash_boot_size = 24K;
__flash_app_size = __FLASH_SIZE - __flash_boot_size;
__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_boot_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
}

71
ports/ch32v20x/port.mk Normal file
View file

@ -0,0 +1,71 @@
UF2_FAMILY_ID = 0x699b62ec
# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
CROSS_COMPILE ?= riscv-none-elf-
CH32_FAMILY = ch32v20x
SDK_DIR = lib/mcu/wch/ch32v20x
SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
CPU_CORE ?= rv32imac-ilp32
CFLAGS += \
-march=rv32imac_zicsr \
-mabi=ilp32 \
# Port0 use FSDev, Port1 use USBFS
USBPORT ?= 0
# Port Compiler Flags
CFLAGS += \
-mcmodel=medany \
-ffat-lto-objects \
-flto \
-DCH32V20x_${MCU_VARIANT} \
-DCFG_TUSB_MCU=OPT_MCU_CH32V20X
ifeq ($(USBPORT),0)
$(info "Using FSDEV driver")
CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1
else
$(info "Using USBFS driver")
CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1
endif
LDFLAGS += \
-nostdlib -nostartfiles \
#--specs=nosys.specs --specs=nano.specs \
# default linker file
ifdef BUILD_APPLICATION
LD_FILES ?= $(PORT_DIR)/linker/${CH32_FAMILY}.ld
else
LD_FILES ?= $(PORT_DIR)/linker/${CH32_FAMILY}_boot.ld
endif
# Port source
SRC_C += \
$(PORT_DIR)/boards.c \
$(PORT_DIR)/system_ch32v20x.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/ch32v20x_flash.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 \
ifndef BUILD_NO_TINYUSB
SRC_C += \
lib/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
lib/tinyusb/src/portable/wch/dcd_ch32_usbfs.c
endif
SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S
# Port include
INC += \
$(TOP)/$(BOARD_DIR) \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
OPENOCD_WCH_OPTION=-f $(TOP)/$(PORT_DIR)/wch-riscv.cfg
flash: flash-openocd-wch

View file

@ -0,0 +1,976 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v20x.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V20x Device Peripheral Access Layer System Source File.
* For HSE = 32Mhz (CH32V208x/CH32V203RBT6)
* For HSE = 8Mhz (other CH32V203x)
*********************************************************************************
* 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 "ch32v20x.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_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
#define SYSCLK_FREQ_144MHz_HSE 144000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
//#define SYSCLK_FREQ_72MHz_HSI 72000000
//#define SYSCLK_FREQ_96MHz_HSI 96000000
//#define SYSCLK_FREQ_120MHz_HSI 120000000
//#define SYSCLK_FREQ_144MHz_HSI 144000000
/* 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_96MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_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) */
#elif defined SYSCLK_FREQ_96MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_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};
/* 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_96MHz_HSE
static void SetSysClockTo96_HSE( void );
#elif defined SYSCLK_FREQ_120MHz_HSE
static void SetSysClockTo120_HSE( void );
#elif defined SYSCLK_FREQ_144MHz_HSE
static void SetSysClockTo144_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 );
#elif defined SYSCLK_FREQ_96MHz_HSI
static void SetSysClockTo96_HSI( void );
#elif defined SYSCLK_FREQ_120MHz_HSI
static void SetSysClockTo120_HSI( void );
#elif defined SYSCLK_FREQ_144MHz_HSI
static void SetSysClockTo144_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, Pll_6_5 = 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(pllmull == 17) pllmull = 18;
if (pllsource == 0x00)
{
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){
SystemCoreClock = HSI_VALUE * pllmull;
}
else{
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
}
else
{
#if defined (CH32V20x_D8W)
if((RCC->CFGR0 & (3<<22)) == (3<<22))
{
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
}
else
#endif
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;
#else
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
#endif
}
else
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = (HSE_VALUE>>2) * pllmull;
#else
SystemCoreClock = HSE_VALUE * pllmull;
#endif
}
}
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
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)
{
#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_96MHz_HSE
SetSysClockTo96_HSE();
#elif defined SYSCLK_FREQ_120MHz_HSE
SetSysClockTo120_HSE();
#elif defined SYSCLK_FREQ_144MHz_HSE
SetSysClockTo144_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();
#elif defined SYSCLK_FREQ_96MHz_HSI
SetSysClockTo96_HSI();
#elif defined SYSCLK_FREQ_120MHz_HSI
SetSysClockTo120_HSI();
#elif defined SYSCLK_FREQ_144MHz_HSI
SetSysClockTo144_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)
{
/* 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
* CH32V20x_D6 (HSE=8MHZ)
* CH32V20x_D8 (HSE=32MHZ)
* CH32V20x_D8W (HSE=32MHZ)
*/
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)
{
/* 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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_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)
{
/* 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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_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)
{
/* 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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_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_96MHz_HSE
/*********************************************************************
* @fn SetSysClockTo96_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_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)
{
/* 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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
/* 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_120MHz_HSE
/*********************************************************************
* @fn SetSysClockTo120_HSE
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_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)
{
#if defined (CH32V20x_D8W)
RCC->CFGR0 |= (uint32_t)(3<<22);
/* HCLK = SYSCLK/2 */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
#else
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
#endif
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
/* 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_144MHz_HSE
/*********************************************************************
* @fn SetSysClockTo144_HSE
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_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)
{
/* 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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
/* 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;
/* 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;
/* 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 = 48 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;
/* 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)
{
}
}
#elif defined SYSCLK_FREQ_96MHz_HSI
/*********************************************************************
* @fn SetSysClockTo96_HSI
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* 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 * 12 = 96 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12);
/* 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_120MHz_HSI
/*********************************************************************
* @fn SetSysClockTo120_HSI
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* 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 * 15 = 120 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15);
/* 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_144MHz_HSI
/*********************************************************************
* @fn SetSysClockTo144_HSI
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* 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 * 18 = 144 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18);
/* 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_ch32v20x.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V20x 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_ch32v20x_H
#define __SYSTEM_ch32v20x_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 /*__CH32V20x_SYSTEM_H */

View file

@ -0,0 +1,100 @@
/*
* 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
//--------------------------------------------------------------------
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#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_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_CDC 0
#define CFG_TUD_MSC 1
#define CFG_TUD_HID 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_BUFSIZE 4096
// HID buffer size Should be sufficient to hold ID (if any) + Data
#define CFG_TUD_HID_BUFSIZE 64
// Vendor FIFO size of TX and RX
// If not configured vendor endpoints will not be buffered
#define CFG_TUD_VENDOR_RX_BUFSIZE 64
#define CFG_TUD_VENDOR_TX_BUFSIZE 64
#ifdef __cplusplus
}
#endif
#endif

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

@ -31,22 +31,6 @@
#include "spi_flash_chip_driver.h"
#include "board_api.h"
// Debug helper, remove later
#define PRINTF(...) ESP_LOGI("uf2", __VA_ARGS__)
#define PRINT_LOCATION() ESP_LOGI("uf2", "%s: %d", __PRETTY_FUNCTION__, __LINE__)
#define PRINT_MESS(x) ESP_LOGI("uf2", "%s", (char*)(x))
#define PRINT_STR(x) ESP_LOGI("uf2", #x " = %s" , (char*)(x) )
#define PRINT_INT(x) ESP_LOGI("uf2", #x " = %d" , (int32_t) (x) )
#define PRINT_HEX(x) ESP_LOGI("uf2", #x " = 0x%X", (uint32_t) (x) )
#define PRINT_BUFFER(buf, n) \
do {\
uint8_t const* p8 = (uint8_t const*) (buf);\
printf(#buf ": ");\
for(uint32_t i=0; i<(n); i++) printf("%x ", p8[i]);\
printf("\n");\
}while(0)
#define FLASH_CACHE_SIZE (64*1024)
#define FLASH_CACHE_INVALID_ADDR 0xffffffff
@ -54,42 +38,36 @@ static uint32_t _fl_addr = FLASH_CACHE_INVALID_ADDR;
static uint8_t _fl_buf[FLASH_CACHE_SIZE] __attribute__((aligned(4)));
// uf2 will always write to ota0 partition
static esp_partition_t const * _part_ota0 = NULL;
static esp_partition_t const* _part_ota0 = NULL;
void board_flash_init(void)
{
void board_flash_init(void) {
_fl_addr = FLASH_CACHE_INVALID_ADDR;
_part_ota0 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
assert(_part_ota0 != NULL);
}
uint32_t board_flash_size(void)
{
uint32_t board_flash_size(void) {
return _part_ota0->size;
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len)
{
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
esp_partition_read(_part_ota0, addr, buffer, len);
}
void board_flash_flush(void)
{
if ( _fl_addr == FLASH_CACHE_INVALID_ADDR ) return;
void board_flash_flush(void) {
if (_fl_addr == FLASH_CACHE_INVALID_ADDR) return;
//PRINTF("Erase and Write at 0x%08X", _fl_addr);
TUF2_LOG1("Erase and Write at 0x%08lX", _fl_addr);
// Check if contents already matched
bool content_matches = true;
uint32_t const verify_sz = 4096;
uint8_t* verify_buf = malloc(verify_sz);
for(uint32_t count = 0; count < FLASH_CACHE_SIZE; count += verify_sz)
{
for (uint32_t count = 0; count < FLASH_CACHE_SIZE; count += verify_sz) {
board_flash_read(_fl_addr + count, verify_buf, verify_sz);
if ( 0 != memcmp(_fl_buf + count, verify_buf, verify_sz) )
{
if (0 != memcmp(_fl_buf + count, verify_buf, verify_sz)) {
content_matches = false;
break;
}
@ -97,8 +75,7 @@ void board_flash_flush(void)
free(verify_buf);
// skip erase & write if content already matches
if ( !content_matches )
{
if (!content_matches) {
esp_partition_erase_range(_part_ota0, _fl_addr, FLASH_CACHE_SIZE);
esp_partition_write(_part_ota0, _fl_addr, _fl_buf, FLASH_CACHE_SIZE);
}
@ -106,12 +83,10 @@ void board_flash_flush(void)
_fl_addr = FLASH_CACHE_INVALID_ADDR;
}
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
{
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
uint32_t new_addr = addr & ~(FLASH_CACHE_SIZE - 1);
if ( new_addr != _fl_addr )
{
if (new_addr != _fl_addr) {
board_flash_flush();
_fl_addr = new_addr;
@ -119,10 +94,11 @@ void board_flash_write (uint32_t addr, void const *data, uint32_t len)
}
memcpy(_fl_buf + (addr & (FLASH_CACHE_SIZE - 1)), data, len);
return true;
}
bool board_flash_protect_bootloader(bool protect)
{
bool board_flash_protect_bootloader(bool protect) {
// TODO implement later
(void) protect;
return false;
@ -134,8 +110,7 @@ bool board_flash_protect_bootloader(bool protect)
//--------------------------------------------------------------------+
#ifdef TINYUF2_SELF_UPDATE
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len) {
enum { SECTOR_SZ = 4096UL };
esp_partition_t const * _part_uf2;

View file

@ -45,8 +45,8 @@
// Flash Start Address of Application
#define BOARD_FLASH_APP_START 0
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 0
// Double Reset tap to enter DFU, for ESP this is done in bootloader subproject
#define TINYUF2_DBL_TAP_DFU 0
#ifdef DISPLAY_PIN_SCK
#define TINYUF2_DISPLAY 1

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" {
@ -42,15 +42,21 @@
#define CFG_TUSB_MCU OPT_MCU_ESP32S3
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_OS OPT_OS_FREERTOS
// Espressif IDF requires "freertos/" prefix in include path
#define CFG_TUSB_OS_INC_PATH freertos/
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -115,4 +121,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -110,8 +110,9 @@ function(family_configure_common TARGET)
# Generate map file
target_link_options(${TARGET} PUBLIC "LINKER:-Map=$<TARGET_FILE:${TARGET}>.map")
#family_add_linkermap(${TARGET})
# All executable target linked with board target
# executable target linked with board target
family_add_board_target(board_${BOARD})
target_link_libraries(${TARGET} PUBLIC board_${BOARD})
@ -162,7 +163,6 @@ function(family_add_tinyusb TARGET OPT_MCU RTOS)
add_subdirectory(${TOP}/lib/tinyusb/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb)
if (RTOS STREQUAL "freertos")
# link tinyusb with freeRTOS kernel
target_link_libraries(${TARGET}-tinyusb PUBLIC freertos_kernel)
endif ()
@ -202,20 +202,15 @@ endfunction()
function(family_configure_tinyuf2 TARGET OPT_MCU)
family_configure_common(${TARGET})
#target_include_directories(${TARGET} PUBLIC)
#target_compile_definitions(${TARGET} PUBLIC)
include(${TOP}/src/tinyuf2.cmake)
add_tinyuf2(${TARGET})
family_add_uf2version(${TARGET} "${FAMILY_SUBMODULE_DEPS}")
family_add_tinyusb(tinyuf2 ${OPT_MCU} none)
family_add_tinyusb(${TARGET} ${OPT_MCU} none)
endfunction()
#----------------------------------
# Output
#----------------------------------
# Add bin/hex output
function(family_add_bin_hex TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin
@ -243,6 +238,11 @@ function(family_add_uf2 TARGET FAMILY_ID)
VERBATIM)
endfunction()
function(family_add_linkermap TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND linkermap -v $<TARGET_FILE:${TARGET}>.map
VERBATIM)
endfunction()
#----------------------------------
# Flashing target
@ -254,6 +254,10 @@ function(family_flash_jlink TARGET)
set(JLINKEXE JLinkExe)
endif ()
if (NOT DEFINED JLINK_IF)
set(JLINK_IF swd)
endif ()
if (ARGC GREATER 1)
set(BIN_FILE $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.${ARGV1})
else ()
@ -271,7 +275,7 @@ exit"
add_custom_target(${TARGET}-jlink
DEPENDS ${TARGET}
COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if swd -JTAGConf -1,-1 -speed auto -CommandFile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jlink
COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if ${JLINK_IF} -JTAGConf -1,-1 -speed auto -CommandFile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jlink
)
endfunction()
@ -289,45 +293,35 @@ function(family_flash_stlink TARGET)
endfunction()
# Add flash pycod targe,t optional parameter is the extension of the binary file (default is elf)
## If bin file is used, address is also required
function(family_flash_pyocd TARGET)
if (NOT DEFINED PYOC)
set(PYOCD pyocd)
# Add flash openocd target
function(family_flash_openocd TARGET)
if (NOT DEFINED OPENOCD)
set(OPENOCD openocd)
endif ()
set(ADDR_OPT "")
if (ARGC GREATER 1)
set(BIN_FILE $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.${ARGV1})
if (${ARGV1} STREQUAL bin)
set(ADDR_OPT "-a ${ARGV2}")
endif ()
else ()
set(BIN_FILE $<TARGET_FILE:${TARGET}>)
if (NOT DEFINED OPENOCD_OPTION2)
set(OPENOCD_OPTION2 "")
endif ()
add_custom_target(${TARGET}-pyocd
separate_arguments(OPTION_LIST UNIX_COMMAND ${OPENOCD_OPTION})
separate_arguments(OPTION_LIST2 UNIX_COMMAND ${OPENOCD_OPTION2})
# note skip verify since it has issue with rp2040
add_custom_target(${TARGET}-openocd
DEPENDS ${TARGET}
COMMAND ${PYOCD} flash -t ${PYOCD_TARGET} ${ADDR_OPT} ${BIN_FILE}
COMMAND ${OPENOCD} ${OPTION_LIST} -c "program $<TARGET_FILE:${TARGET}> reset" ${OPTION_LIST2} -c exit
VERBATIM
)
endfunction()
# Add flash using NXP's LinkServer (redserver)
# https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER
function(family_flash_nxplink TARGET)
if (NOT DEFINED LINKSERVER)
set(LINKSERVER LinkServer)
# Add flash openocd-wch target
# compiled from https://github.com/hathach/riscv-openocd-wch or https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz
function(family_flash_openocd_wch TARGET)
if (NOT DEFINED OPENOCD)
set(OPENOCD $ENV{HOME}/app/riscv-openocd-wch/src/openocd)
endif ()
# LinkServer has a bug that can only execute with full path otherwise it throws:
# realpath error: No such file or directory
execute_process(COMMAND which ${LINKSERVER} OUTPUT_VARIABLE LINKSERVER_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
add_custom_target(${TARGET}-nxplink
DEPENDS ${TARGET}
COMMAND ${LINKSERVER_PATH} flash ${NXPLINK_DEVICE} load $<TARGET_FILE:${TARGET}>
)
family_flash_openocd(${TARGET})
endfunction()

View file

@ -121,8 +121,7 @@ void board_flash_flush(void)
}
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
{
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
uint32_t newAddr = addr & ~(FLASH_PAGE_SIZE - 1);
// int32_t result;
@ -136,8 +135,9 @@ void board_flash_write (uint32_t addr, void const *data, uint32_t len)
// }
}
memcpy(bf_flash_cache + (addr & (FLASH_PAGE_SIZE - 1)), data, len);
}
return true;
}
void board_flash_erase_app(void)
{

View file

@ -32,8 +32,8 @@
#include "board.h"
#include "fsl_rtc.h"
#define TINYUF2_DFU_DOUBLE_TAP 1
#define DBL_TAP_REG RTC->TAR
#define TINYUF2_DBL_TAP_DFU 1
#define TINYUF2_DBL_TAP_REG RTC->TAR
#define BOARD_FLASH_APP_START 0x8000
//#define BOARD_FLASH_SIZE (BOARD_FLASH_TOTAL - BOARD_FLASH_APP_START)

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" {
@ -38,15 +38,17 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -94,4 +96,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -34,17 +34,14 @@
#include "clock_config.h"
#ifndef BUILD_NO_TINYUSB
#include "tusb.h"
#include "tusb.h"
#else
#define TU_LOG1(...)
#define TU_LOG2(...)
#define TU_LOG1(...)
#define TU_LOG2(...)
#endif
#if NEOPIXEL_NUMBER
#include "sct_neopixel.h"
static uint32_t _pixelData[NEOPIXEL_NUMBER] = {0};
#endif
@ -134,7 +131,7 @@ void board_flash_flush(void)
_flash_page_addr = NO_CACHE;
}
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
bool board_flash_write(uint32_t addr, void const* data, uint32_t len)
{
uint32_t newAddr = addr & ~(FLASH_PAGE_SIZE - 1);
int32_t status;
@ -148,6 +145,8 @@ void board_flash_write (uint32_t addr, void const *data, uint32_t len)
}
}
memcpy(_flash_cache + (addr & (FLASH_PAGE_SIZE - 1)), data, len);
return true;
}
void board_flash_erase_app(void)
@ -202,7 +201,7 @@ void board_init(void)
// Init 96 MHz clock
BOARD_BootClockFROHF96M();
// Init RTC for access to DBL_TAP_REG
// Init RTC for access to TINYUF2_DBL_TAP_REG
RTC_Init(RTC);
// disable systick
@ -276,17 +275,8 @@ void board_dfu_init(void)
RESET_PeripheralReset(kUSB1_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB1RAM_RST_SHIFT_RSTn);
#if (defined CFG_TUSB_RHPORT1_MODE) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)
CLOCK_EnableClock(kCLOCK_Usbh1);
/* Put PHY powerdown under software control */
USBHSH->PORTMODE = USBHSH_PORTMODE_SW_PDCOM_MASK;
/* According to reference manual, device mode setting has to be set by access usb host register */
USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
/* enable usb1 host clock */
CLOCK_DisableClock(kCLOCK_Usbh1);
#endif
#if (defined CFG_TUSB_RHPORT0_MODE) && (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE)
#ifndef BUILD_NO_TINYUSB
#if BOARD_TUD_RHPORT == 0
// Enable USB Clock Adjustments to trim the FRO for the full speed controller
ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK;
CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
@ -298,6 +288,17 @@ void board_dfu_init(void)
/* disable usb0 host clock */
CLOCK_DisableClock(kCLOCK_Usbhsl0);
CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); /* enable USB Device clock */
#endif
#if BOARD_TUD_RHPORT == 1
CLOCK_EnableClock(kCLOCK_Usbh1);
/* Put PHY powerdown under software control */
USBHSH->PORTMODE = USBHSH_PORTMODE_SW_PDCOM_MASK;
/* According to reference manual, device mode setting has to be set by access usb host register */
USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
/* enable usb1 host clock */
CLOCK_DisableClock(kCLOCK_Usbh1);
#endif
#endif
TU_LOG2("FRO192M_CTRL: 0x%08lX\r\n", ANACTRL->FRO192M_CTRL);

View file

@ -35,8 +35,8 @@
// Flash Start Address of Application
#define BOARD_FLASH_APP_START 0x10000
#define TINYUF2_DFU_DOUBLE_TAP 1
#define DBL_TAP_REG RTC->GPREG[7]
#define TINYUF2_DBL_TAP_DFU 1
#define TINYUF2_DBL_TAP_REG RTC->GPREG[7]
#ifdef __cplusplus
}

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" {
@ -38,14 +38,18 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
//#define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE
//#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -88,4 +92,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -177,7 +177,7 @@ LDFLAGS += \
# libc
LIBS += -lgcc -lm -lc
# nanolib
# nanolib: TODO remove
ifneq ($(SKIP_NANOLIB), 1)
LDFLAGS += -specs=nosys.specs -specs=nano.specs
LIBS += -lnosys

View file

@ -62,7 +62,6 @@ UF2_MIMXRT1176_ADDR= 0x30000000
SDP_PID = $(SDP_$(MCU)_PID)
UF2_ADDR = $(UF2_$(MCU)_ADDR)
DBL_TAP_MAGIC_ERASE_APP = 0xf5e80ab4
DBL_TAP_REG_ADDR = 0x400D410C
# extract _fcfb_origin and _ivt_origin from linker file

View file

@ -22,5 +22,4 @@ function(configure_app TARGET)
family_add_uf2(${TARGET} ${UF2_FAMILY_ID})
family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
family_flash_jlink(${TARGET} hex)
#family_flash_pyocd(${TARGET} hex)
endfunction()

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" {
@ -38,9 +38,13 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#define CFG_TUSB_RHPORT1_MODE 0
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
@ -83,4 +87,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

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" {
@ -38,9 +38,13 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#define CFG_TUSB_RHPORT1_MODE 0
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
@ -87,4 +91,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

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" {
@ -38,14 +38,17 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define BOARD_TUD_RHPORT 0
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#define CFG_TUSB_RHPORT1_MODE 0
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -88,4 +91,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -181,7 +181,7 @@ void board_flash_flush(void)
_flash_page_addr = NO_CACHE;
}
void board_flash_write (uint32_t addr, void const *src, uint32_t len)
bool board_flash_write (uint32_t addr, void const *src, uint32_t len)
{
uint32_t const page_addr = addr & ~(SECTOR_SIZE - 1);
@ -198,6 +198,8 @@ void board_flash_write (uint32_t addr, void const *src, uint32_t len)
// Overwrite part or all of the page cache with the src data.
memcpy(_flash_cache + (addr & (SECTOR_SIZE - 1)), src, len);
return true;
}
void board_flash_erase_app(void)

View file

@ -423,19 +423,16 @@ int board_uart_read(uint8_t* buf, int len)
#else
void board_uart_init(uint32_t baud_rate)
{
void board_uart_init(uint32_t baud_rate) {
(void) baud_rate;
}
int board_uart_write(void const * buf, int len)
{
int board_uart_write(void const * buf, int len) {
(void) buf; (void) len;
return 0;
}
int board_uart_read(uint8_t* buf, int len)
{
int board_uart_read(uint8_t* buf, int len) {
(void) buf; (void) len;
return 0;
}
@ -449,37 +446,16 @@ int board_uart_read(uint8_t* buf, int len)
// The iMX RT 1040 is named without a number. We can always have this because
// it'll get GC'd when not used.
void USB_OTG_IRQHandler(void)
{
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
tuh_int_handler(0);
#endif
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE
tud_int_handler(0);
#endif
void USB_OTG_IRQHandler(void) {
tud_int_handler(0);
}
void USB_OTG1_IRQHandler(void)
{
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
tuh_int_handler(0);
#endif
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE
tud_int_handler(0);
#endif
void USB_OTG1_IRQHandler(void) {
tud_int_handler(0);
}
void USB_OTG2_IRQHandler(void)
{
#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
tuh_int_handler(1);
#endif
#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE
tud_int_handler(1);
#endif
void USB_OTG2_IRQHandler(void) {
tud_int_handler(1);
}
#endif

View file

@ -57,16 +57,16 @@ extern uint32_t _board_boot_length[];
#endif
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 1
#define DBL_TAP_REG SNVS->LPGPR[3]
#define TINYUF2_DBL_TAP_DFU 1
#define TINYUF2_DBL_TAP_REG SNVS->LPGPR[3]
// Brightness percentage from 1 to 255
#ifndef NEOPIXEL_BRIGHTNESS
#define NEOPIXEL_BRIGHTNESS 0x10
#define NEOPIXEL_BRIGHTNESS 0x10
#endif
#ifdef LED_PIN
#define TINYUF2_LED 1
#define TINYUF2_LED 1
#endif
#ifdef __cplusplus

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" {
@ -38,25 +38,19 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
// Enable Device stack
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#define BOARD_TUD_RHPORT 0
#endif
#if BOARD_TUD_RHPORT == 0
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#define CFG_TUSB_RHPORT1_MODE 0
#elif BOARD_TUD_RHPORT == 1
#define CFG_TUSB_RHPORT0_MODE 0
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
#else
#error "BOARD_TUD_RHPORT is not correct"
#endif
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -71,7 +65,7 @@
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -79,7 +73,7 @@
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
@ -103,4 +97,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -196,3 +196,14 @@ flash-dfu-util: $(BUILD)/$(OUTNAME).bin
erase-dfu-util:
dfu-util -R -a 0 --dfuse-address 0x08000000:mass-erase:force
# --------------- openocd-wch -----------------
# wch-linke is not supported yet in official openOCD yet. We need to either use
# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or
# 2. compiled from https://github.com/hathach/riscv-openocd-wch or
# https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz
# with ./configure --disable-werror --enable-wlinke --enable-ch347=no
OPENOCD_WCH ?= /home/${USER}/app/riscv-openocd-wch/src/openocd
OPENOCD_WCH_OPTION ?=
flash-openocd-wch: $(BUILD)/$(OUTNAME).elf
$(OPENOCD_WCH) $(OPENOCD_WCH_OPTION) -c init -c halt -c "flash write_image $<" -c reset -c exit

View file

@ -39,38 +39,32 @@
#define BOOTLOADER_PAGE_MASK (OB_WRP_PAGES0TO1 | OB_WRP_PAGES2TO3 | OB_WRP_PAGES4TO5 | OB_WRP_PAGES6TO7)
#endif
enum
{
enum {
SECTOR_COUNT = (BOARD_FLASH_SIZE / BOARD_PAGE_SIZE),
BOOTLOADER_SECTOR_COUNT = ((BOARD_FLASH_APP_START - FLASH_BASE_ADDR) / BOARD_PAGE_SIZE)
};
static uint8_t erased_sectors[SECTOR_COUNT] = { 0 };
static uint8_t erased_sectors[SECTOR_COUNT] = {0};
//--------------------------------------------------------------------+
// Internal Helper
//--------------------------------------------------------------------+
static inline uint32_t flash_sector_size(uint32_t sector)
{
static inline uint32_t flash_sector_size(uint32_t sector) {
(void) sector;
return BOARD_PAGE_SIZE;
}
static bool is_blank(uint32_t addr, uint32_t size)
{
for ( uint32_t i = 0; i < size; i += sizeof(uint32_t) )
{
if ( *(uint32_t*) (addr + i) != 0xffffffff )
{
static bool is_blank(uint32_t addr, uint32_t size) {
for (uint32_t i = 0; i < size; i += sizeof(uint32_t)) {
if (*(uint32_t*) (addr + i) != 0xffffffff) {
return false;
}
}
return true;
}
static bool flash_erase_sector(uint32_t addr)
{
static bool flash_erase_sector(uint32_t addr) {
#ifndef TINYUF2_SELF_UPDATE
// skip erasing bootloader if not self-update
TUF2_ASSERT(addr >= BOARD_FLASH_APP_START);
@ -81,13 +75,11 @@ static bool flash_erase_sector(uint32_t addr)
bool erased = false;
uint32_t size = 0;
for ( uint32_t i = 0; i < SECTOR_COUNT; i++ )
{
for (uint32_t i = 0; i < SECTOR_COUNT; i++) {
TUF2_ASSERT(sector_addr < FLASH_BASE_ADDR + BOARD_FLASH_SIZE);
size = flash_sector_size(i);
if ( sector_addr + size > addr )
{
if (sector_addr + size > addr) {
erased = erased_sectors[i];
erased_sectors[i] = 1; // don't erase anymore - we will continue writing here!
break;
@ -95,8 +87,7 @@ static bool flash_erase_sector(uint32_t addr)
sector_addr += size;
}
if ( !erased && !is_blank(sector_addr, size))
{
if (!erased && !is_blank(sector_addr, size)) {
TUF2_LOG1("Erase: %08lX size = %lu KB ... ", sector_addr, size / 1024);
FLASH_EraseInitTypeDef EraseInit;
@ -115,31 +106,26 @@ static bool flash_erase_sector(uint32_t addr)
return true;
}
static void flash_write(uint32_t dst, const uint8_t *src, int len)
{
static void flash_write(uint32_t dst, const uint8_t* src, int len) {
flash_erase_sector(dst);
TUF2_LOG1("Write flash at address %08lX\r\n", dst);
for (int i = 0; i < len; i += 4)
{
uint32_t data = *( (uint32_t*) ((void*) (src + i)) );
for (int i = 0; i < len; i += 4) {
uint32_t data = *((uint32_t*) ((void*) (src + i)));
if ( HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, dst + i, (uint64_t) data) != HAL_OK )
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, dst + i, (uint64_t) data) != HAL_OK) {
TUF2_LOG1("Failed to write flash at address %08lX\r\n", dst + i);
break;
}
if ( FLASH_WaitForLastOperation(HAL_MAX_DELAY) != HAL_OK )
{
if (FLASH_WaitForLastOperation(HAL_MAX_DELAY) != HAL_OK) {
TUF2_LOG1("Waiting on last operation failed\r\n");
return;
}
}
// verify contents
if (memcmp((void*)dst, src, len) != 0)
{
if (memcmp((void*) dst, src, len) != 0) {
TUF2_LOG1("Failed to write\r\n");
}
}
@ -147,45 +133,41 @@ static void flash_write(uint32_t dst, const uint8_t *src, int len)
//--------------------------------------------------------------------+
// Board API
//--------------------------------------------------------------------+
void board_flash_init(void)
{
void board_flash_init(void) {
// nothing to do
}
uint32_t board_flash_size(void)
{
uint32_t board_flash_size(void) {
return BOARD_FLASH_SIZE;
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len)
{
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
memcpy(buffer, (void*) addr, len);
}
void board_flash_flush(void)
{
void board_flash_flush(void) {
// nothing to do
}
// TODO not working quite yet
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
{
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
// TODO skip matching contents
HAL_FLASH_Unlock();
flash_write(addr, data, len);
HAL_FLASH_Lock();
return true;
}
void board_flash_erase_app(void)
{
void board_flash_erase_app(void) {
// TODO implement later
}
bool board_flash_protect_bootloader(bool protect)
{
bool board_flash_protect_bootloader(bool protect) {
// F3 reset every time Option Bytes is programmed
// skip protecting bootloader if we just reset by option byte changes
// since we want to disable protect mode for e.g self-updating
if ( board_reset_by_option_bytes() ) {
if (board_reset_by_option_bytes()) {
return true;
}
@ -203,18 +185,15 @@ bool board_flash_protect_bootloader(bool protect)
TUF2_LOG1("Protection: current = %u, request = %u\r\n", already_protected, protect);
// request and current state mismatched --> require ob program
if (protect != already_protected)
{
if (protect != already_protected) {
FLASH_OBProgramInitTypeDef ob_update = {0};
ob_update.OptionType = OPTIONBYTE_WRP;
ob_update.WRPPage = BOOTLOADER_PAGE_MASK;
ob_update.WRPState = protect ? OB_WRPSTATE_ENABLE : OB_WRPSTATE_DISABLE;
ob_update.WRPPage = BOOTLOADER_PAGE_MASK;
ob_update.WRPState = protect ? OB_WRPSTATE_ENABLE : OB_WRPSTATE_DISABLE;
if (HAL_FLASHEx_OBProgram(&ob_update) == HAL_OK)
{
if (HAL_FLASHEx_OBProgram(&ob_update) == HAL_OK) {
HAL_FLASH_OB_Launch(); // will reset
}else
{
} else {
ret = false;
}
}
@ -227,24 +206,20 @@ bool board_flash_protect_bootloader(bool protect)
#ifdef TINYUF2_SELF_UPDATE
bool is_new_bootloader_valid(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
bool is_new_bootloader_valid(const uint8_t* bootloader_bin, uint32_t bootloader_len) {
// at least larger than vector table
if (bootloader_len < 512 ) return false;
if (bootloader_len < 512) return false;
// similar to board_app_valid() check
if((((*(uint32_t*)bootloader_bin) - BOARD_RAM_START) <= BOARD_RAM_SIZE))
{
if ((((*(uint32_t*) bootloader_bin) - BOARD_RAM_START) <= BOARD_RAM_SIZE)) {
return true;
}
return false;
}
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
void board_self_update(const uint8_t* bootloader_bin, uint32_t bootloader_len) {
// check if the bootloader payload is valid
if ( is_new_bootloader_valid(bootloader_bin, bootloader_len) )
{
if (is_new_bootloader_valid(bootloader_bin, bootloader_len)) {
#if TINYUF2_PROTECT_BOOTLOADER
// Note: Don't protect bootloader when done, leave that to the new bootloader
// since it may or may not enable protection.
@ -252,14 +227,12 @@ void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
#endif
// keep writing until flash contents matches new bootloader data
while( memcmp((const void*) FLASH_BASE_ADDR, bootloader_bin, bootloader_len) )
{
while (memcmp((const void*) FLASH_BASE_ADDR, bootloader_bin, bootloader_len)) {
uint32_t sector_addr = FLASH_BASE_ADDR;
const uint8_t * data = bootloader_bin;
const uint8_t* data = bootloader_bin;
uint32_t len = bootloader_len;
for ( uint32_t i = 0; i < BOOTLOADER_SECTOR_COUNT && len > 0; i++ )
{
for (uint32_t i = 0; i < BOOTLOADER_SECTOR_COUNT && len > 0; i++) {
uint32_t const size = (flash_sector_size(i) < len ? flash_sector_size(i) : len);
board_flash_write(sector_addr, data, size);
@ -275,12 +248,13 @@ void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
__disable_irq();
HAL_FLASH_Unlock();
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOARD_FLASH_APP_START , 0);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOARD_FLASH_APP_START+4, 0);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOARD_FLASH_APP_START, 0);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOARD_FLASH_APP_START + 4, 0);
HAL_FLASH_Lock();
// reset to run new bootloader
NVIC_SystemReset();
}
#endif

View file

@ -328,23 +328,20 @@ int board_uart_write(void const * buf, int len)
#ifndef BUILD_NO_TINYUSB
// Forward USB interrupt events to TinyUSB IRQ Handler
void USB_HP_IRQHandler(void)
{
void USB_HP_IRQHandler(void) {
tud_int_handler(0);
}
// USB low-priority interrupt (Channel 75): Triggered by all USB events
// (Correct transfer, USB reset, etc.). The firmware has to check the
// interrupt source before serving the interrupt.
void USB_LP_IRQHandler(void)
{
void USB_LP_IRQHandler(void) {
tud_int_handler(0);
}
// USB wakeup interrupt (Channel 76): Triggered by the wakeup event from the USB
// Suspend mode.
void USBWakeUp_RMP_IRQHandler(void)
{
void USBWakeUp_RMP_IRQHandler(void) {
tud_int_handler(0);
}
@ -352,7 +349,5 @@ void USBWakeUp_RMP_IRQHandler(void)
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
__attribute__((used)) void _init(void)
{
__attribute__((used)) void _init(void) {
}

View file

@ -47,7 +47,7 @@
#define BOARD_RAM_SIZE 0x9FFF
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 1
#define TINYUF2_DBL_TAP_DFU 1
// Enable write protection
#ifndef TINYUF2_PROTECT_BOOTLOADER

View file

@ -62,7 +62,3 @@ function(family_add_board_target BOARD_TARGET)
--specs=nosys.specs --specs=nano.specs
)
endfunction()
#------------------------------------
# Main target
#------------------------------------

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" {
@ -38,21 +38,19 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_DEVICE_RHPORT_NUM
#define BOARD_DEVICE_RHPORT_NUM 0
#endif
// RHPort max operational speed can defined by board.mk
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
// This example doesn't use an RTOS
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -67,7 +65,7 @@
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -95,4 +93,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -193,12 +193,14 @@ void board_flash_flush(void)
}
// TODO not working quite yet
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
bool board_flash_write(uint32_t addr, void const* data, uint32_t len)
{
// TODO skip matching contents
HAL_FLASH_Unlock();
flash_write(addr, data, len);
HAL_FLASH_Lock();
return true;
}
void board_flash_erase_app(void)

View file

@ -42,7 +42,7 @@
#endif
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 1
#define TINYUF2_DBL_TAP_DFU 1
// Enable write protection
#ifndef TINYUF2_PROTECT_BOOTLOADER

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" {
@ -38,12 +38,18 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -58,7 +64,7 @@
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -91,4 +97,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -152,9 +152,10 @@ void board_flash_read(uint32_t addr, void * data, uint32_t len)
}
}
void board_flash_write(uint32_t addr, void const * data, uint32_t len)
bool board_flash_write(uint32_t addr, void const * data, uint32_t len)
{
TUF2_LOG1("Programming %lu byte(s) at 0x%08lx\r\n", len, addr);
// For external flash, W25Qx
// TODO: these should be configurable parameters
// Page size = 256 bytes
@ -163,7 +164,7 @@ void board_flash_write(uint32_t addr, void const * data, uint32_t len)
if (IS_SPI_ADDR(addr) && IS_SPI_ADDR(addr + len - 1))
{
W25Qx_Write((uint8_t *) data, (addr - SPI_BASE_ADDR), len);
return;
return true;
}
#endif
@ -176,7 +177,7 @@ void board_flash_write(uint32_t addr, void const * data, uint32_t len)
{
__asm("bkpt #9");
}
return;
return true;
}
#endif
@ -186,7 +187,7 @@ void board_flash_write(uint32_t addr, void const * data, uint32_t len)
// This memory is cached, DCache is cleaned in dfu_complete
SET_BOOT_ADDR(BOARD_AXISRAM_APP_ADDR);
memcpy((void *) addr, data, len);
return;
return true;
}
#endif // BOARD_AXISRAM_EN
@ -198,13 +199,12 @@ void board_flash_write(uint32_t addr, void const * data, uint32_t len)
{
// TODO: Implement this
// SET_BOOT_ADDR(BOARD_PFLASH_APP_ADDR);
return;
return false;
}
{
// Invalid address write
__asm("bkpt #4");
}
// Invalid address write
__asm("bkpt #4");
return false;
}
void board_flash_erase_app(void)

View file

@ -53,7 +53,7 @@ void board_init(void)
void board_dfu_init(void)
{
// Not quite sure what an RHPORT is :/
#if BOARD_DEVICE_RHPORT_NUM == 0
#if BOARD_TUD_RHPORT == 0
GPIO_InitTypeDef GPIO_InitStruct;
// Init USB Pins
@ -81,9 +81,9 @@ void board_dfu_init(void)
USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
#elif BOARD_DEVICE_RHPORT_NUM == 1
// TODO: implement whatever this is
#error "Sorry, not implemented yet"
#elif BOARD_TUD_RHPORT == 1
// TODO: implement whatever this is
#error "Sorry, not implemented yet"
#endif
}

View file

@ -77,7 +77,7 @@
#define SET_BOOT_ADDR(x) board_save_app_start_address(x)
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 1
#define TINYUF2_DBL_TAP_DFU 1
void board_flash_early_init(void);
uint32_t board_get_app_start_address(void);

View file

@ -84,7 +84,7 @@ extern "C" {
#define UF2_INDEX_URL "https://github.com/WeActStudio/MiniSTM32H7xx"
#define USB_NO_VBUS_PIN 1
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_TUD_RHPORT 0
//--------------------------------------------------------------------+
// UART

View file

@ -67,7 +67,7 @@ SRC_C += \
ifndef BUILD_NO_TINYUSB
SRC_C += lib/tinyusb/src/portable/st/synopsys/dcd_synopsys.c
SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c
endif
# Includes

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" {
@ -38,17 +38,18 @@
#error CFG_TUSB_MCU must be defined in board.mk
#endif
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_DEVICE_RHPORT_NUM
#define BOARD_DEVICE_RHPORT_NUM 0
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -92,10 +93,8 @@
#define CFG_TUD_VENDOR_RX_BUFSIZE 64
#define CFG_TUD_VENDOR_TX_BUFSIZE 64
#define CFG_TUSB_RHPORT1_MODE 0
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -162,12 +162,14 @@ void board_flash_flush(void)
}
// TODO not working quite yet
void board_flash_write (uint32_t addr, void const *data, uint32_t len)
bool board_flash_write(uint32_t addr, void const* data, uint32_t len)
{
// TODO skip matching contents
HAL_FLASH_Unlock();
flash_write(addr, data, len);
HAL_FLASH_Lock();
return true;
}
void board_flash_erase_app(void)

View file

@ -44,7 +44,7 @@
#define BOARD_PAGE_SIZE 0x1000
// Double Reset tap to enter DFU
#define TINYUF2_DFU_DOUBLE_TAP 1
#define TINYUF2_DBL_TAP_DFU 1
// Brightness percentage from 1 to 255
#ifndef NEOPIXEL_BRIGHTNESS

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" {
@ -35,15 +35,21 @@
//--------------------------------------------------------------------
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined in board.mk
#error CFG_TUSB_MCU must be defined
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
// Enable Device stack
#define CFG_TUD_ENABLED 1
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
@ -58,7 +64,7 @@
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -66,7 +72,7 @@
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
@ -91,4 +97,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -23,43 +23,42 @@
*/
#include "board_api.h"
#ifndef BUILD_NO_TINYUSB
#include "tusb.h"
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
void board_init(void)
{
void board_init(void) {
}
void board_dfu_init(void)
{
void board_teardown(void) {
}
void board_dfu_init(void) {
// Init USB for DFU
}
void board_reset(void)
{
void board_reset(void) {
// NVIC_SystemReset();
}
void board_dfu_complete(void)
{
void board_dfu_complete(void) {
// Mostly reset
// NVIC_SystemReset();
}
bool board_app_valid(void)
{
bool board_app_valid(void) {
return false;
}
void board_app_jump(void)
{
void board_app_jump(void) {
// Jump to application code
}
uint8_t board_usb_get_serial(uint8_t serial_id[16])
{
uint8_t board_usb_get_serial(uint8_t serial_id[16]) {
(void) serial_id;
return 0;
}
@ -68,13 +67,11 @@ uint8_t board_usb_get_serial(uint8_t serial_id[16])
// LED pattern
//--------------------------------------------------------------------+
void board_led_write(uint32_t state)
{
void board_led_write(uint32_t state) {
(void) state;
}
void board_rgb_write(uint8_t const rgb[])
{
void board_rgb_write(uint8_t const rgb[]) {
(void) rgb;
}
@ -82,35 +79,78 @@ void board_rgb_write(uint8_t const rgb[])
// Timer
//--------------------------------------------------------------------+
void board_timer_start(uint32_t ms)
{
void board_timer_start(uint32_t ms) {
(void) ms;
// SysTick_Config( (SystemCoreClock/1000) * ms );
}
void board_timer_stop(void)
{
void board_timer_stop(void) {
// SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Handler (void)
{
void SysTick_Handler(void) {
board_timer_handler();
}
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;
}
#ifndef TINYUF2_SELF_UPDATE
//--------------------------------------------------------------------+
// Flash
//--------------------------------------------------------------------+
void board_flash_init(void) {
// Forward USB interrupt events to TinyUSB IRQ Handler
void OTG_FS_IRQHandler(void)
{
tud_int_handler(0);
}
uint32_t board_flash_size(void) {
return 0;
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
(void) addr;
(void) buffer;
(void) len;
}
void board_flash_flush(void) {
}
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
(void) addr;
(void) data;
(void) len;
return true;
}
void board_flash_erase_app(void) {
// TODO implement later
}
bool board_flash_protect_bootloader(bool protect) {
// TODO implement later
(void) protect;
return false;
}
#ifdef TINYUF2_SELF_UPDATE
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
(void) bootloader_bin;
(void) bootloader_len;
}
#endif
//--------------------------------------------------------------------+
// USB Interrupt Handler
//--------------------------------------------------------------------+
#ifndef BUILD_NO_TINYUSB
// Forward USB interrupt events to TinyUSB IRQ Handler
void OTG_FS_IRQHandler(void) {
tud_int_handler(0);
}
#endif

View file

@ -31,7 +31,7 @@
#include "board.h"
#define TINYUF2_DFU_DOUBLE_TAP 0
#define TINYUF2_DBL_TAP_DFU 0
#ifdef __cplusplus
}

View file

@ -0,0 +1,2 @@
function(update_board TARGET)
endfunction()

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" {
@ -35,17 +35,19 @@
//--------------------------------------------------------------------
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined in board.mk
#error CFG_TUSB_MCU must be defined
#endif
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
// can be defined by compiler in DEBUG build
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif
// Enable Device stack
#define CFG_TUD_ENABLED 1
/* 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.
@ -58,7 +60,7 @@
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -66,7 +68,7 @@
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
@ -91,4 +93,4 @@
}
#endif
#endif /* _TUSB_CONFIG_H_ */
#endif

View file

@ -27,46 +27,46 @@
uint32_t board_flash_size(void) { return CFG_UF2_FLASH_SIZE; }
// not supported
void board_flash_write(uint32_t addr, void const *data, uint32_t len) {
(void)addr;
(void)data;
(void)len;
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
(void) addr;
(void) data;
(void) len;
return true;
}
// not supported
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len) {
(void)bootloader_bin;
(void)bootloader_len;
void board_self_update(const uint8_t* bootloader_bin, uint32_t bootloader_len) {
(void) bootloader_bin;
(void) bootloader_len;
}
// not supported
void board_flash_flush(void) {}
void board_flash_flush(void) {}
// not supported
bool board_flash_protect_bootloader(bool protect)
{
bool board_flash_protect_bootloader(bool protect) {
(void) protect;
return false;
}
//------------- Interesting part of flash support for this test -------------//
void board_flash_read (uint32_t addr, void* buffer, uint32_t len) {
if ((addr & 7) != 0) {
// TODO - need to copy part of the first eight bytes
exit(1); // failure exit
addr += 8 - (addr & 7);
}
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
if ((addr & 7) != 0) {
// TODO - need to copy part of the first eight bytes
exit(1); // failure exit
addr += 8 - (addr & 7);
}
// EMBED address in each 32 bits of the FLASH
uint32_t * dest = buffer;
size_t incBytes = sizeof(*dest);
uint32_t currentAddress = addr;
// EMBED address in each 32 bits of the FLASH
uint32_t* dest = buffer;
size_t incBytes = sizeof(*dest);
uint32_t currentAddress = addr;
while (len >= incBytes) {
memcpy(dest, &currentAddress, incBytes); // unaligned memory possible
while (len >= incBytes) {
memcpy(dest, &currentAddress, incBytes); // unaligned memory possible
len -= incBytes;
dest++;
currentAddress += incBytes;
}
len -= incBytes;
dest++;
currentAddress += incBytes;
}
}

View file

@ -30,6 +30,23 @@
#include <string.h>
#include "boards.h"
//--------------------------------------------------------------------+
// Compiler
//--------------------------------------------------------------------+
#define TUF2_TOKEN(x) x
#define TUF2_STRING(x) #x // stringify without expand
#define TUF2_XSTRING(x) TU_STRING(x) // expand then stringify
#define TUF2_STRCAT(a, b) a##b // concat without expand
#define TUF2_STRCAT3(a, b, c) a##b##c // concat without expand
#define TUF2_XSTRCAT(a, b) TU_STRCAT(a, b) // expand then concat
#define TUF2_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) // expand then concat 3 tokens
#define ATTR_WEAK __attribute__ ((weak))
#define ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
//--------------------------------------------------------------------+
// Features
//--------------------------------------------------------------------+
@ -43,14 +60,28 @@
#define BOARD_FLASH_APP_START 0
#endif
#ifndef TUF2_LOG
#define TUF2_LOG 2
#endif
// Use LED for part of indicator
#ifndef TINYUF2_LED
#define TINYUF2_LED 0
#endif
// Use Double Tap method to enter DFU mode
#ifndef TINYUF2_DFU_DOUBLE_TAP
#define TINYUF2_DFU_DOUBLE_TAP 0
#ifndef TINYUF2_DBL_TAP_DFU
#define TINYUF2_DBL_TAP_DFU 0
#endif
// timeout for double tap detection in ms
#ifndef TINYUF2_DBL_TAP_DELAY
#define TINYUF2_DBL_TAP_DELAY 500
#endif
#ifndef TINYUF2_DBL_TAP_REG_SIZE
#define TINYUF2_DBL_TAP_REG_SIZE 32
#endif
// Use Display to draw DFU image
@ -68,10 +99,6 @@
#define TINYUF2_CONST
#endif
#ifndef TUF2_LOG
#define TUF2_LOG 0
#endif
// Use favicon.ico + autorun.inf (only works with windows)
// define TINYUF2_FAVICON_HEADER to enable this feature
@ -79,9 +106,26 @@
// Constant
//--------------------------------------------------------------------+
#define DBL_TAP_MAGIC 0xf01669ef // Enter DFU magic
#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef // Skip double tap delay detection
#define DBL_TAP_MAGIC_ERASE_APP 0xf5e80ab4 // Erase entire application !!
// defined by linker script
#if TINYUF2_DBL_TAP_REG_SIZE == 32
#define DBL_TAP_TYPE uint32_t
#elif TINYUF2_DBL_TAP_REG_SIZE == 16
#define DBL_TAP_TYPE uint16_t
#elif TINYUF2_DBL_TAP_REG_SIZE == 8
#define DBL_TAP_TYPE uint8_t
#else
#error "Invalid TINYUF2_DBL_TAP_REG_SIZE"
#endif
#ifndef TINYUF2_DBL_TAP_REG
// defined by linker script
extern DBL_TAP_TYPE _board_dfu_dbl_tap[];
#define TINYUF2_DBL_TAP_REG _board_dfu_dbl_tap[0]
#endif
#define DBL_TAP_MAGIC (0xf01669ef >> (32 - TINYUF2_DBL_TAP_REG_SIZE)) // Enter DFU magic
#define DBL_TAP_MAGIC_QUICK_BOOT (0xf02669ef >> (32 - TINYUF2_DBL_TAP_REG_SIZE)) // Skip double tap delay detection
#define DBL_TAP_MAGIC_ERASE_APP (0xf5e80ab4 >> (32 - TINYUF2_DBL_TAP_REG_SIZE)) // Erase entire application !!
//--------------------------------------------------------------------+
// Basic API
@ -105,7 +149,7 @@ void board_teardown(void) __attribute__ ((weak));
// board_teardown2() is called immediately after board_init()
void board_teardown2(void) __attribute__ ((weak));
// Reset board, not return
// Reset board, no return
void board_reset(void);
// Write PWM duty value to LED
@ -135,7 +179,7 @@ bool board_app_valid(void);
// Additional check if application is valid for custom board.
bool board_app_valid2(void) __attribute__ ((weak));
// Jump to Application
// Jump to Application, no return
void board_app_jump(void);
// Init USB hardware (not used for now)
@ -150,6 +194,9 @@ void board_dfu_complete(void);
// Fill Serial Number and return its length (limit to 16 bytes)
uint8_t board_usb_get_serial(uint8_t serial_id[16]);
// Check if NRST pin is used to reset the board
// bool board_reseted_by_nrst(void);
//--------------------------------------------------------------------+
// Flash API
//--------------------------------------------------------------------+
@ -163,8 +210,8 @@ uint32_t board_flash_size(void);
// Read from flash
void board_flash_read (uint32_t addr, void* buffer, uint32_t len);
// Write to flash
void board_flash_write(uint32_t addr, void const *data, uint32_t len);
// Write to flash, len is uf2's payload size (often 256 bytes)
bool board_flash_write(uint32_t addr, void const* data, uint32_t len);
// Flush/Sync flash contents
void board_flash_flush(void);
@ -219,12 +266,12 @@ void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len);
#define TUF2_LOG1_MEM // tu_print_mem
#define TUF2_LOG1_VAR(_x) // tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
#define TUF2_LOG1_INT(_x) tuf2_printf(#_x " = %ld\r\n", (uint32_t) (_x) )
#define TUF2_LOG1_HEX(_x) tuf2_printf(#_x " = %lX\r\n", (uint32_t) (_x) )
#define TUF2_LOG1_HEX(_x) tuf2_printf(#_x " = 0x%lX\r\n", (uint32_t) (_x) )
#define TUF2_LOG1_LOCATION() tuf2_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
#define TUF2_LOG1_FAILED() tuf2_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
// Log with debug level 2
#if CFG_TUSB_DEBUG > 1
#if TUF2_LOG > 1
#define TUF2_LOG2 TUF2_LOG1
#define TUF2_LOG2_MEM TUF2_LOG1_MEM
#define TUF2_LOG2_VAR TUF2_LOG1_VAR
@ -268,10 +315,8 @@ enum {
void indicator_set(uint32_t state);
static inline void rgb_brightness(uint8_t out[3], uint8_t const in[3], uint8_t brightness)
{
for(uint32_t i=0; i<3; i++ )
{
static inline void rgb_brightness(uint8_t out[3], uint8_t const in[3], uint8_t brightness) {
for(uint32_t i=0; i<3; i++ ) {
out[i] = (in[i]*brightness) >> 8;
}
}

View file

@ -26,7 +26,6 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include "compile_date.h"
@ -141,7 +140,7 @@ char infoUf2File[128*3] =
"Date: " COMPILE_DATE "\r\n"
"Flash Size: 0x";
const char indexFile[] =
TINYUF2_CONST char indexFile[] =
"<!doctype html>\n"
"<html>"
"<body>"
@ -201,7 +200,7 @@ STATIC_ASSERT( CLUSTER_COUNT >= 0x1015 && CLUSTER_COUNT < 0xFFD5 );
//
//--------------------------------------------------------------------+
static FAT_BootBlock const BootBlock = {
static FAT_BootBlock TINYUF2_CONST BootBlock = {
.JumpInstruction = {0xeb, 0x3c, 0x90},
.OEMInfo = "UF2 UF2 ",
.SectorSize = BPB_SECTOR_SIZE,

View file

@ -37,21 +37,12 @@
//--------------------------------------------------------------------+
//#define USE_DFU_BUTTON 1
// timeout for double tap detection
#define DBL_TAP_DELAY 500
#ifndef DBL_TAP_REG
// defined by linker script
extern uint32_t _board_dfu_dbl_tap[];
#define DBL_TAP_REG _board_dfu_dbl_tap[0]
#endif
uint8_t const RGB_USB_UNMOUNTED[] = { 0xff, 0x00, 0x00 }; // Red
uint8_t const RGB_USB_MOUNTED[] = { 0x00, 0xff, 0x00 }; // Green
uint8_t const RGB_WRITING[] = { 0xcc, 0x66, 0x00 };
uint8_t const RGB_DOUBLE_TAP[] = { 0x80, 0x00, 0xff }; // Purple
uint8_t const RGB_UNKNOWN[] = { 0x00, 0x00, 0x88 }; // for debug
uint8_t const RGB_OFF[] = { 0x00, 0x00, 0x00 };
uint8_t RGB_USB_UNMOUNTED[] = { 0xff, 0x00, 0x00 }; // Red
uint8_t RGB_USB_MOUNTED[] = { 0x00, 0xff, 0x00 }; // Green
uint8_t RGB_WRITING[] = { 0xcc, 0x66, 0x00 };
uint8_t RGB_DOUBLE_TAP[] = { 0x80, 0x00, 0xff }; // Purple
uint8_t RGB_UNKNOWN[] = { 0x00, 0x00, 0x88 }; // for debug
uint8_t RGB_OFF[] = { 0x00, 0x00, 0x00 };
static volatile uint32_t _timer_count = 0;
@ -63,7 +54,7 @@ static bool check_dfu_mode(void);
int main(void) {
board_init();
if (board_init2) board_init2();
TU_LOG1("TinyUF2\r\n");
TUF2_LOG1("TinyUF2\r\n");
#if TINYUF2_PROTECT_BOOTLOADER
board_flash_protect_bootloader(true);
@ -75,14 +66,16 @@ int main(void) {
if (board_teardown) board_teardown();
if (board_teardown2) board_teardown2();
board_app_jump();
TU_LOG1("Failed to jump\r\n");
while (1) {}
}
TU_LOG1("Start DFU mode\r\n");
TUF2_LOG1("Start DFU mode\r\n");
board_dfu_init();
board_flash_init();
uf2_init();
tusb_init();
tud_init(BOARD_TUD_RHPORT);
indicator_set(STATE_USB_UNPLUGGED);
@ -91,7 +84,7 @@ int main(void) {
screen_draw_drag();
#endif
#if (CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO)
#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
while(1) {
tud_task();
}
@ -100,44 +93,46 @@ int main(void) {
// return true if start DFU mode, else App mode
static bool check_dfu_mode(void) {
// TODO enable for all port instead of one with double tap
#if TINYUF2_DFU_DOUBLE_TAP
// TUF2_LOG1_HEX(&DBL_TAP_REG);
// Erase application
if (DBL_TAP_REG == DBL_TAP_MAGIC_ERASE_APP) {
DBL_TAP_REG = 0;
indicator_set(STATE_WRITING_STARTED);
board_flash_erase_app();
indicator_set(STATE_WRITING_FINISHED);
// TODO maybe reset is better than continue
}
#endif
// Check if app is valid
if (!board_app_valid()) return true;
if (board_app_valid2 && !board_app_valid2()) return true;
#if TINYUF2_DFU_DOUBLE_TAP
// TU_LOG1_HEX(DBL_TAP_REG);
// App want to reboot quickly
if (DBL_TAP_REG == DBL_TAP_MAGIC_QUICK_BOOT) {
DBL_TAP_REG = 0;
return false;
if (!board_app_valid()) {
TUF2_LOG1("App invalid\r\n");
return true;
}
if (DBL_TAP_REG == DBL_TAP_MAGIC) {
// Double tap occurred
DBL_TAP_REG = 0;
TU_LOG1("Double Tap Reset\r\n");
if (board_app_valid2 && !board_app_valid2()) {
TUF2_LOG1("App invalid\r\n");
return true;
}
#if TINYUF2_DBL_TAP_DFU
TUF2_LOG1_HEX(TINYUF2_DBL_TAP_REG);
switch(TINYUF2_DBL_TAP_REG) {
case DBL_TAP_MAGIC_QUICK_BOOT:
// Boot to app quickly
TUF2_LOG1("Quick boot to App\r\n");
TINYUF2_DBL_TAP_REG = 0;
return false;
case DBL_TAP_MAGIC:
// Double tap occurred
TUF2_LOG1("Double Tap Reset\r\n");
TINYUF2_DBL_TAP_REG = 0;
return true;
case DBL_TAP_MAGIC_ERASE_APP:
TUF2_LOG1("Erase app\r\n");
TINYUF2_DBL_TAP_REG = 0;
indicator_set(STATE_WRITING_STARTED);
board_flash_erase_app();
indicator_set(STATE_WRITING_FINISHED);
return true;
default:
break;
}
// Register our first reset for double reset detection
DBL_TAP_REG = DBL_TAP_MAGIC;
TINYUF2_DBL_TAP_REG = DBL_TAP_MAGIC;
_timer_count = 0;
board_timer_start(1);
@ -150,14 +145,14 @@ static bool check_dfu_mode(void) {
board_rgb_write(RGB_DOUBLE_TAP);
// delay a fraction of second if Reset pin is tap during this delay --> we will enter dfu
while(_timer_count < DBL_TAP_DELAY) {}
while(_timer_count < TINYUF2_DBL_TAP_DELAY) {}
board_timer_stop();
// Turn off indicator
board_rgb_write(RGB_OFF);
board_led_write(0x00);
DBL_TAP_REG = 0;
TINYUF2_DBL_TAP_REG = 0;
#endif
return false;
@ -181,27 +176,27 @@ void tud_umount_cb(void) {
// Indicator
//--------------------------------------------------------------------+
static uint32_t _indicator_state = STATE_BOOTLOADER_STARTED;
static uint8_t _indicator_rgb[3];
static uint32_t indicator_state = STATE_BOOTLOADER_STARTED;
static uint8_t indicator_rgb[3];
void indicator_set(uint32_t state) {
_indicator_state = state;
indicator_state = state;
switch (state) {
case STATE_USB_UNPLUGGED:
board_timer_start(1);
memcpy(_indicator_rgb, RGB_USB_UNMOUNTED, 3);
board_rgb_write(_indicator_rgb);
memcpy(indicator_rgb, RGB_USB_UNMOUNTED, 3);
board_rgb_write(indicator_rgb);
break;
case STATE_USB_PLUGGED:
board_timer_start(5);
memcpy(_indicator_rgb, RGB_USB_MOUNTED, 3);
board_rgb_write(_indicator_rgb);
memcpy(indicator_rgb, RGB_USB_MOUNTED, 3);
board_rgb_write(indicator_rgb);
break;
case STATE_WRITING_STARTED:
board_timer_start(25);
memcpy(_indicator_rgb, RGB_WRITING, 3);
memcpy(indicator_rgb, RGB_WRITING, 3);
break;
case STATE_WRITING_FINISHED:
@ -217,7 +212,7 @@ void indicator_set(uint32_t state) {
void board_timer_handler(void) {
_timer_count++;
switch (_indicator_state) {
switch (indicator_state) {
case STATE_USB_UNPLUGGED:
case STATE_USB_PLUGGED: {
// Fading with LED TODO option to skip for unsupported MCUs
@ -240,7 +235,7 @@ void board_timer_handler(void) {
board_led_write(is_on ? 0xff : 0x000);
// blink RGB if available
board_rgb_write(is_on ? _indicator_rgb : RGB_OFF);
board_rgb_write(is_on ? indicator_rgb : RGB_OFF);
break;
}
@ -254,7 +249,7 @@ void board_timer_handler(void) {
//--------------------------------------------------------------------+
// Enable only with LOG is enabled (Note: ESP32-S2 has built-in support already)
#if CFG_TUSB_DEBUG && (CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_RP2040)
#if (CFG_TUSB_DEBUG || TUF2_LOG) && (CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_RP2040)
#if defined(LOGGER_RTT)
#include "SEGGER_RTT.h"
#endif

View file

@ -35,7 +35,7 @@
static uint32_t _write_ms;
#endif
static WriteState _wr_state = { 0 };
static WriteState _wr_state = {0};
//--------------------------------------------------------------------+
// tinyusb callbacks
@ -43,23 +43,21 @@ static WriteState _wr_state = { 0 };
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
{
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
(void) lun;
const char vid[] = "Adafruit";
const char pid[] = "UF2 Bootloader";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(vendor_id, vid, strlen(vid));
memcpy(product_id, pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
(void) lun;
return true;
}
@ -67,20 +65,18 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun)
// Callback invoked when received an SCSI command not in built-in list below
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 has their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
{
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
void const* response = NULL;
uint16_t resplen = 0;
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0])
{
switch (scsi_cmd[0]) {
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
// Host is about to read/write etc ... better not to disconnect disk
resplen = 0;
break;
break;
default:
// Set Sense = Invalid Command Operation
@ -88,19 +84,16 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
// negative means error -> tinyusb could stall and/or response with failed status
resplen = -1;
break;
break;
}
// return resplen must not larger than bufsize
if ( resplen > bufsize ) resplen = bufsize;
if (resplen > bufsize) resplen = bufsize;
if ( response && (resplen > 0) )
{
if(in_xfer)
{
if (response && (resplen > 0)) {
if (in_xfer) {
memcpy(buffer, response, resplen);
}else
{
} else {
// SCSI output
}
}
@ -110,8 +103,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
{
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void) lun;
memset(buffer, 0, bufsize);
@ -120,13 +112,12 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf
uint32_t count = 0;
while ( count < bufsize )
{
while (count < bufsize) {
uf2_read_block(lba, buffer);
lba++;
buffer += 512;
count += 512;
count += 512;
}
return count;
@ -134,43 +125,36 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and return number of written bytes
int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
{
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) {
(void) lun;
(void) offset;
uint32_t count = 0;
while ( count < bufsize )
{
while (count < bufsize) {
// Consider non-uf2 block write as successful
// only break if write_block is busy with flashing (return 0)
if ( 0 == uf2_write_block(lba, buffer, &_wr_state) ) break;
if (0 == uf2_write_block(lba, buffer, &_wr_state)) break;
lba++;
buffer += 512;
count += 512;
count += 512;
}
return count;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
void tud_msc_write10_complete_cb(uint8_t lun)
{
void tud_msc_write10_complete_cb(uint8_t lun) {
(void) lun;
static bool first_write = true;
// abort the DFU, uf2 block failed integrity check
if ( _wr_state.aborted )
{
if (_wr_state.aborted) {
// aborted and reset
indicator_set(STATE_WRITING_FINISHED);
}
else if ( _wr_state.numBlocks )
{
} else if (_wr_state.numBlocks) {
// Start LED writing pattern with first write
if (first_write)
{
if (first_write) {
#if DEBUG_SPEED_TEST
_write_ms = esp_log_timestamp();
#endif
@ -180,8 +164,7 @@ void tud_msc_write10_complete_cb(uint8_t lun)
}
// All block of uf2 file is complete --> complete DFU process
if (_wr_state.numWritten >= _wr_state.numBlocks)
{
if (_wr_state.numWritten >= _wr_state.numBlocks) {
#if DEBUG_SPEED_TEST
uint32_t const wr_byte = _wr_state.numWritten*256;
_write_ms = esp_log_timestamp()-_write_ms;
@ -189,41 +172,37 @@ void tud_msc_write10_complete_cb(uint8_t lun)
printf("Speed : %.02f KB/s\r\n", (wr_byte / 1000.0F) / (_write_ms / 1000.0F));
#endif
TUF2_LOG1("Writing finished\r\n");
indicator_set(STATE_WRITING_FINISHED);
board_dfu_complete();
// board_dfu_complete() should not return
// getting here is an indicator of error
while(1) {}
while (1) {}
}
}
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
{
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) {
(void) lun;
*block_count = CFG_UF2_NUM_BLOCKS;
*block_size = 512;
*block_size = 512;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
{
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
(void) lun;
(void) power_condition;
if ( load_eject )
{
if (start)
{
if (load_eject) {
if (start) {
// load disk storage
}else
{
} else {
// unload disk storage
}
}

View file

@ -104,7 +104,7 @@ uint8_t const* tud_descriptor_device_cb(void) {
#define EPNUM_CDC_IN 0x83
#endif
uint8_t const desc_configuration[] = {
uint8_t TINYUF2_CONST desc_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
#if CFG_TUD_CDC
@ -152,7 +152,6 @@ static uint16_t _desc_str[48 + 1];
// 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;
uint8_t chr_count;
switch (index) {
@ -161,12 +160,10 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
chr_count = 1;
break;
// TODO light alternation such as +1 to prevent conflict with application
// TODO light alternation such as +1 to prevent conflict with application
case STRID_SERIAL: {
uint8_t serial_id[16] TU_ATTR_ALIGNED(4);
uint8_t serial_len;
serial_len = board_usb_get_serial(serial_id);
uint8_t serial_len = board_usb_get_serial(serial_id);
chr_count = 2 * serial_len;
for (uint8_t i = 0; i < serial_len; i++) {
@ -174,7 +171,6 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
const char nibble_to_hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
uint8_t nibble = (serial_id[i] >> (j * 4)) & 0xf;
_desc_str[1 + i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE
}

View file

@ -38,9 +38,9 @@ deps_optional = {
'lib/mcu/st/stm32l4xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git',
'aee3d5bf283ae5df87532b781bdd01b7caf256fc',
'stm32l4'],
# 'lib/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git',
# 'c4c38f507e258a4e69b059ccc2dc27dde33cea1b',
# 'ch32v20x'],
'lib/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git',
'c4c38f507e258a4e69b059ccc2dc27dde33cea1b',
'ch32v20x'],
'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git',
'497ca8974927e3b853fd80c8fc35f4e557af79b9',
'lpc55'],