From 010f88dd3fc3823d6f448c89908046510ca42fff Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sat, 2 May 2026 12:42:07 +0800 Subject: [PATCH 1/2] Add support for APM32F072 --- .../boards/apm32f072_dev_board/board.cmake | 8 + .../boards/apm32f072_dev_board/board.h | 49 ++++++ .../boards/apm32f072_dev_board/board.mk | 7 + hw/bsp/apm32f0xx/family.c | 145 ++++++++++++++++++ hw/bsp/apm32f0xx/family.cmake | 84 ++++++++++ hw/bsp/apm32f0xx/family.mk | 39 +++++ src/common/tusb_mcu.h | 8 + src/portable/st/stm32_fsdev/fsdev_apm32.h | 77 ++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 2 + src/tusb_option.h | 3 + 10 files changed, 422 insertions(+) create mode 100644 hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake create mode 100644 hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.h create mode 100644 hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk create mode 100644 hw/bsp/apm32f0xx/family.c create mode 100644 hw/bsp/apm32f0xx/family.cmake create mode 100644 hw/bsp/apm32f0xx/family.mk create mode 100644 src/portable/st/stm32_fsdev/fsdev_apm32.h diff --git a/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake new file mode 100644 index 0000000000..33148dbd43 --- /dev/null +++ b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT APM32F072xB) +set(MCU_LINKER_NAME APM32F07xxB) + +set(JLINK_DEVICE APM32F072RB) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.h b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.h new file mode 100644 index 0000000000..2c9e567e52 --- /dev/null +++ b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.h @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: APM32F072 Dev Board + url: https://www.geehy.com +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PORT GPIOC +#define LED_PIN GPIO_PIN_13 +#define LED_STATE_ON 0 +#define LED_GPIO_CLK_EN() RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOC) + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk new file mode 100644 index 0000000000..2e5df99471 --- /dev/null +++ b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = APM32F072xB +MCU_LINKER_NAME = APM32F07xxB + +JLINK_DEVICE = APM32F072RB + +CFLAGS += \ + -D${MCU_VARIANT} diff --git a/hw/bsp/apm32f0xx/family.c b/hw/bsp/apm32f0xx/family.c new file mode 100644 index 0000000000..cbc427f8cf --- /dev/null +++ b/hw/bsp/apm32f0xx/family.c @@ -0,0 +1,145 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + manufacturer: Geehy +*/ + +#include "apm32f0xx.h" +#include "apm32f0xx_rcm.h" +#include "apm32f0xx_gpio.h" +#include "apm32f0xx_misc.h" +#include "apm32f0xx_crs.h" +#include "bsp/board_api.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// Board Init +//--------------------------------------------------------------------+ +void board_init(void) { + // Enable HSI48 for USB clock + RCM_EnableHSI48(); + while (RCM_ReadStatusFlag(RCM_FLAG_HSI48RDY) == RESET) {} + + // Select HSI48 as USB clock source + RCM_ConfigUSBCLK(RCM_USBCLK_HSI48); + + // Enable CRS for automatic HSI48 calibration from USB SOF + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CRS); + CRS_ConfigSynchronizationSource(CRS_SYNC_SOURCE_USB); + CRS_EnableAutomaticCalibration(); + CRS_EnableFrequencyErrorCounter(); + + // Enable USB peripheral clock + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_USB); + + // SysTick 1ms tick + SysTick_Config(SystemCoreClock / 1000); + + // LED + LED_GPIO_CLK_EN(); + GPIO_Config_T gpio_config; + GPIO_ConfigStructInit(&gpio_config); + gpio_config.pin = LED_PIN; + gpio_config.mode = GPIO_MODE_OUT; + gpio_config.outtype = GPIO_OUT_TYPE_PP; + gpio_config.speed = GPIO_SPEED_50MHz; + GPIO_Config(LED_PORT, &gpio_config); + + board_led_write(false); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ +void board_led_write(bool state) { + if (state ^ (!LED_STATE_ON)) { + GPIO_SetBit(LED_PORT, LED_PIN); + } else { + GPIO_ClearBit(LED_PORT, LED_PIN); + } +} + +uint32_t board_button_read(void) { + return 0; +} + +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + (void) max_len; + volatile uint32_t *apm32_uuid = ((volatile uint32_t *) 0x1FFFF7AC); + uint32_t *id32 = (uint32_t *) (uintptr_t) id; + uint8_t const len = 12; + + id32[0] = apm32_uuid[0]; + id32[1] = apm32_uuid[1]; + id32[2] = apm32_uuid[2]; + + return len; +} + +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; + return 0; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler(void) { + system_ticks++; +} + +uint32_t tusb_time_millis_api(void) { + return system_ticks; +} + +void SVC_Handler(void) { +} + +void PendSV_Handler(void) { +} +#endif + +void HardFault_Handler(void) { + __asm("BKPT #0\n"); +} + +void _init(void) { +} diff --git a/hw/bsp/apm32f0xx/family.cmake b/hw/bsp/apm32f0xx/family.cmake new file mode 100644 index 0000000000..99a94a7a85 --- /dev/null +++ b/hw/bsp/apm32f0xx/family.cmake @@ -0,0 +1,84 @@ +include_guard() + +set(APM32_FAMILY apm32f0xx) +set(APM32_SDK ${TOP}/hw/mcu/geehy/APM32F0xx_SDK_V1.8.6/Libraries) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS APM32F0XX CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(STARTUP_FILE_GNU ${APM32_SDK}/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${APM32_SDK}/Device/Geehy/APM32F0xx/Source/gcc/gcc_${MCU_LINKER_NAME}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${APM32_SDK}/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c + ${APM32_SDK}/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c + ${APM32_SDK}/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c + ${APM32_SDK}/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c + ${APM32_SDK}/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${APM32_SDK}/CMSIS/Include + ${APM32_SDK}/Device/Geehy/APM32F0xx/Include + ${APM32_SDK}/APM32F0xx_StdPeriphDriver/inc + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_APM32F0XX) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/apm32f0xx/family.mk b/hw/bsp/apm32f0xx/family.mk new file mode 100644 index 0000000000..73a762d69e --- /dev/null +++ b/hw/bsp/apm32f0xx/family.mk @@ -0,0 +1,39 @@ +APM32_FAMILY = apm32f0xx +APM32_SDK = hw/mcu/geehy/APM32F0xx_SDK_V1.8.6/Libraries + +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= cortex-m0plus + +CFLAGS += \ + -flto + +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_APM32F0XX + +LDFLAGS += \ + -flto --specs=nosys.specs -nostdlib -nostartfiles + +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ + $(APM32_SDK)/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c \ + $(APM32_SDK)/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c \ + $(APM32_SDK)/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c \ + $(APM32_SDK)/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c \ + $(APM32_SDK)/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(APM32_SDK)/APM32F0xx_StdPeriphDriver/inc \ + $(TOP)/$(APM32_SDK)/CMSIS/Include \ + $(TOP)/$(APM32_SDK)/Device/Geehy/APM32F0xx/Include + +SRC_S += $(APM32_SDK)/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S + +LD_FILE ?= $(APM32_SDK)/Device/Geehy/APM32F0xx/Source/gcc/gcc_${MCU_LINKER_NAME}.ld + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 + +flash: flash-jlink diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index c85ade4d05..353e856ccc 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -698,6 +698,14 @@ #define TU_ATTR_FAST_FUNC __attribute__((section(".fast"))) +//--------------------------------------------------------------------+ +// Geehy +//--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_APM32F0XX) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_APM32 + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u + #endif // External USB controller diff --git a/src/portable/st/stm32_fsdev/fsdev_apm32.h b/src/portable/st/stm32_fsdev/fsdev_apm32.h new file mode 100644 index 0000000000..5031445e81 --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_apm32.h @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +#ifndef TUSB_FSDEV_APM32_H +#define TUSB_FSDEV_APM32_H + +#include "common/tusb_compiler.h" + +#if CFG_TUSB_MCU == OPT_MCU_APM32F0XX + #include "apm32f0xx.h" +#endif + +#define FSDEV_USE_SBUF_ISO 0 +#define FSDEV_REG_BASE ((uint32_t)(USBD_BASE)) +#define FSDEV_PMA_BASE ((uint32_t)(USBD_BASE + 0x400UL)) + +#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP + #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 +#endif + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +static const IRQn_Type fsdev_irq[] = { + USBD_IRQn +}; +enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; + +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { + (void)rhport; + for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) { + NVIC_EnableIRQ(fsdev_irq[i]); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { + (void)rhport; + for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) { + NVIC_DisableIRQ(fsdev_irq[i]); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR |= U_CNTR_PDWN; + FSDEV_REG->BCDR &= ~U_BCDR_DPPU; +} + +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR &= ~U_CNTR_PDWN; + FSDEV_REG->BCDR |= U_BCDR_DPPU; +} + +#endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index af84b8b97c..29918d16c6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -303,6 +303,8 @@ typedef struct { #include "fsdev_ch32.h" #elif defined(TUP_USBIP_FSDEV_AT32) #include "fsdev_at32.h" +#elif defined(TUP_USBIP_FSDEV_APM32) + #include "fsdev_apm32.h" #else #error "Unknown USB IP" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 154f8e2a40..40ec37acf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -220,6 +220,9 @@ // HPMicro #define OPT_MCU_HPM 2600 ///< HPMicro +// Geehy +#define OPT_MCU_APM32F0XX 2700 ///< Geehy APM32F0xx + // Check if configured MCU is one of listed // Apply TU_MCU_IS_EQUAL with || as separator to list of input #define TU_MCU_IS_EQUAL(_m) (CFG_TUSB_MCU == (_m)) From df124b78584089decd054abfd454afb358d0400d Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sat, 2 May 2026 12:50:04 +0800 Subject: [PATCH 2/2] Update docs --- README.rst | 2 ++ docs/reference/boards.rst | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/README.rst b/README.rst index 04998abaaa..8b916fadcf 100644 --- a/README.rst +++ b/README.rst @@ -160,6 +160,8 @@ Supported CPUs | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | S31 | ✔ | ✔ | ✔ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Geehy APM32 | F072 | ✔ | | ✖ | fsdev | 1KB USB RAM | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | HPMicro | HPM6750 | ✔ | ✔ | ✔ | ci_hs, ehci | | diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index e61c4f98bf..52d85e2ccf 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -81,6 +81,15 @@ espressif_s3_devkitm Espresif S3 DevKitM espressif https://do espressif_saola_1 Espresif S2 Saola 1 espressif https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/esp32-s2-saola-1/index.html ========================= ============================== ========= ======================================================================================================== ====== +Geehy +----- + +==================== ==================== ========= ============================================== ====== +Board Name Family URL Note +==================== ==================== ========= ============================================== ====== +apm32f072_dev_board APM32F072 Dev Board apm32f0xx +==================== ==================== ========= ============================================== ====== + GigaDevice ----------