summaryrefslogtreecommitdiff
path: root/hw/bsp/py32f0
diff options
context:
space:
mode:
Diffstat (limited to 'hw/bsp/py32f0')
-rw-r--r--hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h108
-rw-r--r--hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake12
-rw-r--r--hw/bsp/py32f0/boards/py32f071_dev_board/board.h75
-rw-r--r--hw/bsp/py32f0/boards/py32f071_dev_board/board.mk12
-rw-r--r--hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h105
-rw-r--r--hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld122
-rw-r--r--hw/bsp/py32f0/family.c133
-rw-r--r--hw/bsp/py32f0/family.cmake89
-rw-r--r--hw/bsp/py32f0/family.mk58
9 files changed, 714 insertions, 0 deletions
diff --git a/hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..6b3ae0cd5
--- /dev/null
+++ b/hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h
@@ -0,0 +1,108 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2026, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef FREERTOS_CONFIG_H_
+#define FREERTOS_CONFIG_H_
+
+#ifndef __IASMARM__
+ #include "py32f0xx.h"
+#endif
+
+#define configENABLE_MPU 0
+#define configENABLE_FPU 0
+#define configENABLE_TRUSTZONE 0
+#define configMINIMAL_SECURE_STACK_SIZE 1024
+
+#define configUSE_PREEMPTION 1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#define configCPU_CLOCK_HZ SystemCoreClock
+#define configTICK_RATE_HZ 1000
+#define configMAX_PRIORITIES 5
+#define configMINIMAL_STACK_SIZE 128
+#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION * 4 * 1024 )
+#define configMAX_TASK_NAME_LEN 16
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configQUEUE_REGISTRY_SIZE 4
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 0
+#define configUSE_NEWLIB_REENTRANT 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
+#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
+
+#define configSUPPORT_STATIC_ALLOCATION 1
+#define configSUPPORT_DYNAMIC_ALLOCATION 0
+
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configUSE_MALLOC_FAILED_HOOK 0
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
+
+#define configGENERATE_RUN_TIME_STATS 0
+#define configRECORD_STACK_HIGH_ADDRESS 1
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES 2
+
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
+#define configTIMER_QUEUE_LENGTH 32
+#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
+
+#define INCLUDE_vTaskPrioritySet 0
+#define INCLUDE_uxTaskPriorityGet 0
+#define INCLUDE_vTaskDelete 0
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_xResumeFromISR 0
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 0
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#define INCLUDE_pcTaskGetTaskName 0
+#define INCLUDE_eTaskGetState 0
+#define INCLUDE_xEventGroupSetBitFromISR 0
+#define INCLUDE_xTimerPendFunctionCall 0
+
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+#define vPortSVCHandler SVC_Handler
+
+#define configPRIO_BITS __NVIC_PRIO_BITS
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ( ( 1 << configPRIO_BITS ) - 1 )
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
+
+#endif
diff --git a/hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake b/hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake
new file mode 100644
index 000000000..e759f4af1
--- /dev/null
+++ b/hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake
@@ -0,0 +1,12 @@
+set(PYOCD_TARGET py32f071xb)
+set(PY32_SERIES PY32F071)
+set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/py32f071xb.ld)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ PY32F071xB
+ CFG_EXAMPLE_MSC_READONLY
+ CFG_EXAMPLE_MSC_DUAL_READONLY
+ CFG_EXAMPLE_VIDEO_READONLY
+ )
+endfunction()
diff --git a/hw/bsp/py32f0/boards/py32f071_dev_board/board.h b/hw/bsp/py32f0/boards/py32f071_dev_board/board.h
new file mode 100644
index 000000000..ddd67bb6a
--- /dev/null
+++ b/hw/bsp/py32f0/boards/py32f071_dev_board/board.h
@@ -0,0 +1,75 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2026, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define LED_PORT GPIOB
+#define LED_PIN GPIO_PIN_2
+#define LED_STATE_ON 0
+
+#define BUTTON_PORT GPIOB
+#define BUTTON_PIN GPIO_PIN_0
+#define BUTTON_STATE_ACTIVE 0
+
+static inline void board_py32f0_clock_init(void) {
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI |
+ RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
+ RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+ RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
+ RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_16MHz;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz;
+ RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
+ RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
+ while (1) {}
+ }
+
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
+ while (1) {}
+ }
+}
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/py32f0/boards/py32f071_dev_board/board.mk b/hw/bsp/py32f0/boards/py32f071_dev_board/board.mk
new file mode 100644
index 000000000..e7fbc338d
--- /dev/null
+++ b/hw/bsp/py32f0/boards/py32f071_dev_board/board.mk
@@ -0,0 +1,12 @@
+PY32_SERIES = PY32F071
+
+CFLAGS += \
+ -DPY32F071xB \
+ -DCFG_EXAMPLE_MSC_READONLY \
+ -DCFG_EXAMPLE_MSC_DUAL_READONLY \
+ -DCFG_EXAMPLE_VIDEO_READONLY
+
+LD_FILE = $(BOARD_PATH)/py32f071xb.ld
+PYOCD_TARGET = py32f071xb
+
+flash: flash-pyocd
diff --git a/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h b/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h
new file mode 100644
index 000000000..e513bf8cb
--- /dev/null
+++ b/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h
@@ -0,0 +1,105 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2026, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef PY32F071_HAL_CONF_H_
+#define PY32F071_HAL_CONF_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define HAL_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+#if !defined(HSI_VALUE)
+ #define HSI_VALUE ((uint32_t) 8000000)
+#endif
+
+#if !defined(HSE_VALUE)
+ #define HSE_VALUE ((uint32_t) 24000000)
+#endif
+
+#if !defined(HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t) 200)
+#endif
+
+#if !defined(LSI_VALUE)
+ #define LSI_VALUE ((uint32_t) 32768)
+#endif
+
+#if !defined(LSE_VALUE)
+ #define LSE_VALUE ((uint32_t) 32768)
+#endif
+
+#if !defined(LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t) 5000)
+#endif
+
+#define VDD_VALUE ((uint32_t) 3300)
+#define TICK_INT_PRIORITY ((uint32_t) 3)
+#define USE_RTOS 0
+#define PREFETCH_ENABLE 0
+
+#ifdef HAL_MODULE_ENABLED
+ #include "py32f0xx_hal.h"
+#endif
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "py32f071_hal_rcc.h"
+#endif
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "py32f071_hal_flash.h"
+#endif
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "py32f071_hal_gpio.h"
+#endif
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "py32f071_hal_pwr.h"
+#endif
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "py32f071_hal_cortex.h"
+#endif
+
+#ifdef USE_FULL_ASSERT
+void assert_failed(uint8_t *file, uint32_t line);
+ #define assert_param(expr) ((expr) ? (void) 0U : assert_failed((uint8_t *) __FILE__, __LINE__))
+#else
+ #define assert_param(expr) ((void) 0U)
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld b/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld
new file mode 100644
index 000000000..bb6b88d2c
--- /dev/null
+++ b/hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld
@@ -0,0 +1,122 @@
+ENTRY(Reset_Handler)
+
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+_Min_Heap_Size = 0x200;
+_Min_Stack_Size = 0x400;
+
+MEMORY
+{
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+}
+
+SECTIONS
+{
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector))
+ . = ALIGN(4);
+ } >FLASH
+
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text)
+ *(.text*)
+ *(.glue_7)
+ *(.glue_7t)
+ *(.eh_frame)
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ . = ALIGN(4);
+ _etext = .;
+ } >FLASH
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ *(.rodata)
+ *(.rodata*)
+ . = ALIGN(4);
+ } >FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >FLASH
+
+ .ARM :
+ {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >FLASH
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN(__preinit_array_start = .);
+ KEEP(*(.preinit_array*))
+ PROVIDE_HIDDEN(__preinit_array_end = .);
+ } >FLASH
+
+ .init_array :
+ {
+ PROVIDE_HIDDEN(__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array*))
+ PROVIDE_HIDDEN(__init_array_end = .);
+ } >FLASH
+
+ .fini_array :
+ {
+ PROVIDE_HIDDEN(__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array*))
+ PROVIDE_HIDDEN(__fini_array_end = .);
+ } >FLASH
+
+ _sidata = LOADADDR(.data);
+
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .;
+ *(.data)
+ *(.data*)
+ . = ALIGN(4);
+ _edata = .;
+ } >RAM AT> FLASH
+
+ . = ALIGN(4);
+ .bss :
+ {
+ _sbss = .;
+ __bss_start__ = _sbss;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ __bss_end__ = _ebss;
+ } >RAM
+
+ ._user_heap_stack :
+ {
+ . = ALIGN(8);
+ PROVIDE(end = .);
+ PROVIDE(_end = .);
+ . = . + _Min_Heap_Size;
+ . = . + _Min_Stack_Size;
+ . = ALIGN(8);
+ } >RAM
+
+ /DISCARD/ :
+ {
+ libc.a(*)
+ libm.a(*)
+ libgcc.a(*)
+ }
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/hw/bsp/py32f0/family.c b/hw/bsp/py32f0/family.c
new file mode 100644
index 000000000..1428b1fa9
--- /dev/null
+++ b/hw/bsp/py32f0/family.c
@@ -0,0 +1,133 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2026, 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: Puya
+*/
+
+#include "py32f0xx_hal.h"
+#include "bsp/board_api.h"
+#include "board.h"
+
+void USB_IRQHandler(void) {
+ tud_int_handler(0);
+}
+
+void USBD_IRQHandler(void) {
+ tud_int_handler(0);
+}
+
+void HAL_MspInit(void) {
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ __HAL_RCC_PWR_CLK_ENABLE();
+}
+
+void board_init(void) {
+ HAL_Init();
+ board_py32f0_clock_init();
+
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ __HAL_RCC_PWR_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+ SysTick_Config(SystemCoreClock / 1000);
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+ SysTick->CTRL &= ~1U;
+ NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
+#endif
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ GPIO_InitStruct.Pin = LED_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+ board_led_write(false);
+
+ GPIO_InitStruct.Pin = BUTTON_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
+
+ __HAL_RCC_USB_CLK_ENABLE();
+}
+
+void board_led_write(bool state) {
+ GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON));
+ HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state);
+}
+
+uint32_t board_button_read(void) {
+ return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
+}
+
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ (void) max_len;
+ volatile uint32_t * py32_uuid = (volatile uint32_t *) UID_BASE;
+ uint32_t* id32 = (uint32_t*) (uintptr_t) id;
+ uint8_t const len = 12;
+
+ id32[0] = py32_uuid[0];
+ id32[1] = py32_uuid[1];
+ id32[2] = py32_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 -1;
+}
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+
+void SysTick_Handler(void) {
+ HAL_IncTick();
+ system_ticks++;
+}
+
+uint32_t tusb_time_millis_api(void) {
+ return system_ticks;
+}
+#endif
+
+void HardFault_Handler(void) {
+ __asm("BKPT #0\n");
+}
+
+void _init(void);
+void _init(void) {
+}
diff --git a/hw/bsp/py32f0/family.cmake b/hw/bsp/py32f0/family.cmake
new file mode 100644
index 000000000..df6dec42b
--- /dev/null
+++ b/hw/bsp/py32f0/family.cmake
@@ -0,0 +1,89 @@
+include_guard()
+
+include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+if (NOT DEFINED MCU_VARIANT)
+ set(MCU_VARIANT PY32F071)
+endif ()
+string(TOLOWER ${MCU_VARIANT} PY32_SERIES_LOWER)
+set(PY32_SDK_NAME ${MCU_VARIANT}_Firmware)
+set(PY32_TEMPLATE ${MCU_VARIANT}xx_Templates)
+set(PY32_STARTUP startup_${PY32_SERIES_LOWER}xx.s)
+set(PY32_SYSTEM_SOURCE system_${PY32_SERIES_LOWER}.c)
+set(PY32_HAL_PREFIX ${PY32_SERIES_LOWER})
+
+set(PY32_SDK ${TOP}/hw/mcu/puya/${PY32_SDK_NAME})
+set(PY32_HAL ${PY32_SDK}/Drivers/${MCU_VARIANT}_HAL_Driver)
+set(PY32_CMSIS ${PY32_SDK}/Drivers/CMSIS/Device/${MCU_VARIANT})
+
+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 PY32F0 CACHE INTERNAL "")
+
+set(STARTUP_FILE_GNU ${PY32_SDK}/Templates/${PY32_TEMPLATE}/EIDE/${PY32_STARTUP})
+set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
+set(LD_FILE_Clang ${LD_FILE_GNU})
+
+function(family_add_board BOARD_TARGET)
+ add_library(${BOARD_TARGET} STATIC
+ ${PY32_SDK}/Templates/${PY32_TEMPLATE}/Src/${PY32_SYSTEM_SOURCE}
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_cortex.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_flash.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_gpio.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_pwr.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_rcc.c
+ ${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_rcc_ex.c
+ )
+ target_include_directories(${BOARD_TARGET} PUBLIC
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ ${PY32_SDK}/Drivers/CMSIS/Include
+ ${PY32_CMSIS}/Include
+ ${PY32_HAL}/Inc
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+ )
+ target_compile_definitions(${BOARD_TARGET} PRIVATE
+ USE_HAL_DRIVER
+ )
+ update_board(${BOARD_TARGET})
+endfunction()
+
+function(family_configure_example TARGET RTOS)
+ family_configure_common(${TARGET} ${RTOS})
+ family_add_tinyusb(${TARGET} OPT_MCU_PY32F0)
+
+ target_sources(${TARGET} PUBLIC
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
+ ${TOP}/src/portable/mentor/musb/dcd_musb.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")
+ message(FATAL_ERROR "Clang is not supported")
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ message(FATAL_ERROR "IAR is not supported")
+ endif ()
+
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
+ endif ()
+ set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
+ SKIP_LINTING ON
+ COMPILE_OPTIONS -w)
+
+ family_add_bin_hex(${TARGET})
+ family_flash_pyocd(${TARGET})
+endfunction()
diff --git a/hw/bsp/py32f0/family.mk b/hw/bsp/py32f0/family.mk
new file mode 100644
index 000000000..b01a9eefa
--- /dev/null
+++ b/hw/bsp/py32f0/family.mk
@@ -0,0 +1,58 @@
+UF2_FAMILY_ID = 0x0
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+
+MCU_VARIANT ?= PY32F071
+PY32_SERIES_LOWER = $(subst PY32F,py32f,$(MCU_VARIANT))
+PY32_SDK_NAME = $(MCU_VARIANT)_Firmware
+PY32_TEMPLATE = $(MCU_VARIANT)xx_Templates
+PY32_STARTUP = startup_$(PY32_SERIES_LOWER)xx.s
+PY32_SYSTEM_SOURCE = system_$(PY32_SERIES_LOWER).c
+PY32_HAL_PREFIX = $(PY32_SERIES_LOWER)
+
+SDK_DIR = hw/mcu/puya/$(PY32_SDK_NAME)
+HAL_DIR = $(SDK_DIR)/Drivers/$(MCU_VARIANT)_HAL_Driver
+CMSIS_DIR = $(SDK_DIR)/Drivers/CMSIS
+CMSIS_DEVICE_DIR = $(CMSIS_DIR)/Device/$(MCU_VARIANT)
+
+DEPS_SUBMODULES += $(SDK_DIR)
+
+CFLAGS += \
+ -DCFG_TUSB_MCU=OPT_MCU_PY32F0 \
+ -DUSE_HAL_DRIVER
+
+# Puya HAL leaves some CMSIS-compatible callback parameters intentionally unused.
+CFLAGS += -Wno-error=unused-parameter
+
+MCU_DIR = $(SDK_DIR)
+
+SRC_C += \
+ src/portable/mentor/musb/dcd_musb.c \
+ hw/bsp/py32f0/family.c \
+ $(SDK_DIR)/Templates/$(PY32_TEMPLATE)/Src/$(PY32_SYSTEM_SOURCE) \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_cortex.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_flash.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_gpio.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_pwr.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_rcc.c \
+ $(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_rcc_ex.c
+
+SRC_S += $(SDK_DIR)/Templates/$(PY32_TEMPLATE)/EIDE/$(PY32_STARTUP)
+
+INC += \
+ $(TOP)/hw/bsp/py32f0 \
+ $(TOP)/$(CMSIS_DIR)/Include \
+ $(TOP)/$(CMSIS_DEVICE_DIR)/Include \
+ $(TOP)/$(HAL_DIR)/Inc \
+ $(TOP)/hw/bsp/py32f0/boards/$(BOARD)
+
+SKIP_NANOLIB = 1
+
+LDFLAGS += \
+ -nostdlib -nostartfiles \
+ --specs=nosys.specs --specs=nano.specs \
+ -Wl,--gc-sections \
+ -Wl,--print-memory-usage
+
+CPU_CORE ?= cortex-m0plus