summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-25 09:27:48 +0200
committerHiFiPHile <[email protected]>2026-08-25 09:27:48 +0200
commitdfac26a272fa7bbbca2050fbe9f1ca09008e548e (patch)
treeefbc53f8f2c1e5d9c7f38e5fef6d774a20053cec /hw
parente590b45fcf51f9ddace73178074e4fe6d691e319 (diff)
parent5c0e31cdabaf37f14e1f5e988a020abfc1000495 (diff)
Merge master updates into the UAC1 host branch
Bring the audio work onto the current host core and build files before applying the remaining review fixes. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'hw')
-rw-r--r--hw/bsp/BoardPresets.json44
-rw-r--r--hw/bsp/apm32f0xx/FreeRTOSConfig/FreeRTOSConfig.h108
-rw-r--r--hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake13
-rw-r--r--hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.h49
-rw-r--r--hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk10
-rw-r--r--hw/bsp/apm32f0xx/family.c146
-rw-r--r--hw/bsp/apm32f0xx/family.cmake83
-rw-r--r--hw/bsp/apm32f0xx/family.mk38
-rw-r--r--hw/bsp/ch32v10x/family.cmake2
-rw-r--r--hw/bsp/ch32v10x/family.mk2
-rw-r--r--hw/bsp/ch32v20x/family.c38
-rw-r--r--hw/bsp/ch32v20x/family.cmake2
-rw-r--r--hw/bsp/ch32v20x/family.mk2
-rw-r--r--hw/bsp/ch32v30x/family.c9
-rw-r--r--hw/bsp/ch32v30x/family.cmake2
-rw-r--r--hw/bsp/ch32v30x/family.mk2
-rw-r--r--hw/bsp/ch583/family.cmake2
-rw-r--r--hw/bsp/ch583/family.mk2
-rw-r--r--hw/bsp/ch583/wch-riscv.cfg2
-rw-r--r--hw/bsp/family_rules.mk16
-rw-r--r--hw/bsp/family_support.cmake44
-rw-r--r--hw/bsp/imxrt/boards/metro_m7_1011/ozone/metro_m7_1011.jdebug3
-rw-r--r--hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h5
-rw-r--r--hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176.jdebug69
-rw-r--r--hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176_trace.JLinkScript11
-rw-r--r--hw/bsp/imxrt/family.c73
-rw-r--r--hw/bsp/kinetis_k/family.c40
-rw-r--r--hw/bsp/kinetis_k/family.cmake2
-rw-r--r--hw/bsp/kinetis_k/family.mk4
-rw-r--r--hw/bsp/kinetis_k32l/family.cmake4
-rw-r--r--hw/bsp/kinetis_k32l/family.mk4
-rw-r--r--hw/bsp/kinetis_kl/family.cmake2
-rw-r--r--hw/bsp/kinetis_kl/family.mk4
-rw-r--r--hw/bsp/lpc11/boards/lpcxpresso11u37/board.mk3
-rw-r--r--hw/bsp/lpc11/boards/lpcxpresso11u37/lpc11u37.ld16
-rw-r--r--hw/bsp/lpc15/family.c13
-rw-r--r--hw/bsp/lpc18/boards/lpcxpresso18s37/board.h6
-rw-r--r--hw/bsp/lpc18/boards/mcb1800/board.h27
-rw-r--r--hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug6
-rw-r--r--hw/bsp/lpc18/family.c1
-rw-r--r--hw/bsp/lpc40/boards/ea4088_quickstart/ozone/ea4088_quickstart.jdebug2
-rw-r--r--hw/bsp/lpc40/family.c13
-rw-r--r--hw/bsp/lpc43/boards/ea4357/board.h16
-rw-r--r--hw/bsp/lpc43/boards/lpcxpresso43s67/board.h6
-rw-r--r--hw/bsp/lpc43/family.c30
-rw-r--r--hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake4
-rw-r--r--hw/bsp/lpc55/boards/lpcxpresso55s28/board.mk6
-rw-r--r--hw/bsp/lpc55/family.c8
-rw-r--r--hw/bsp/lpc55/family.mk2
-rw-r--r--hw/bsp/mcx/family.cmake11
-rw-r--r--hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug2
-rw-r--r--hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug6
-rw-r--r--hw/bsp/nrf/family.c6
-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
-rw-r--r--hw/bsp/ra/boards/ra6m5_ek/ozone/ra6m5.jdebug2
-rw-r--r--hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1.jdebug17
-rw-r--r--hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1_trace.JLinkScript20
-rw-r--r--hw/bsp/ra/boards/ra8m1_ek/ra_gen/bsp_clock_cfg.h5
-rw-r--r--hw/bsp/ra/family.c29
-rw-r--r--hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake14
-rw-r--r--hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug70
-rw-r--r--hw/bsp/rp2040/family.c29
-rw-r--r--hw/bsp/rp2040/family.cmake2
-rw-r--r--hw/bsp/samd5x_e5x/boards/same54_xplained/ozone/same54.jdebug89
-rw-r--r--hw/bsp/samd5x_e5x/family.c27
-rw-r--r--hw/bsp/same7x/boards/same70_xplained/board.h4
-rw-r--r--hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug115
-rw-r--r--hw/bsp/same7x/family.c32
-rw-r--r--hw/bsp/stm32h5/boards/stm32h563nucleo/board.h5
-rw-r--r--hw/bsp/stm32h5/boards/stm32h563nucleo/ozone/stm32h563.jdebug113
-rw-r--r--hw/bsp/stm32h5/family.c20
-rw-r--r--hw/bsp/stm32h5/linker/stm32h533xx_flash.icf32
-rw-r--r--hw/bsp/stm32h7/boards/stm32h743eval/ozone/stm32h743.jdebug3
-rw-r--r--hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h6
-rw-r--r--hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3.jdebug94
-rw-r--r--hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3_trace.JLinkScript11
-rw-r--r--hw/bsp/stm32h7rs/family.c19
-rw-r--r--hw/bsp/stm32l4/boards/stm32l412nucleo/board.h48
-rw-r--r--hw/bsp/stm32n6/boards/stm32n657nucleo/board.h6
-rw-r--r--hw/bsp/stm32n6/boards/stm32n657nucleo/ozone/stm32n657.jdebug94
-rw-r--r--hw/bsp/stm32n6/family.c22
89 files changed, 2501 insertions, 162 deletions
diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json
index 93a8f2c32..a480efc3e 100644
--- a/hw/bsp/BoardPresets.json
+++ b/hw/bsp/BoardPresets.json
@@ -43,6 +43,10 @@
"inherits": "default"
},
{
+ "name": "apm32f072_dev_board",
+ "inherits": "default"
+ },
+ {
"name": "arduino_nano33_ble",
"inherits": "default"
},
@@ -511,6 +515,10 @@
"inherits": "default"
},
{
+ "name": "py32f071_dev_board",
+ "inherits": "default"
+ },
+ {
"name": "pybadge",
"inherits": "default"
},
@@ -1008,6 +1016,11 @@
"configurePreset": "apard32690"
},
{
+ "name": "apm32f072_dev_board",
+ "description": "Build preset for the apm32f072_dev_board board",
+ "configurePreset": "apm32f072_dev_board"
+ },
+ {
"name": "arduino_nano33_ble",
"description": "Build preset for the arduino_nano33_ble board",
"configurePreset": "arduino_nano33_ble"
@@ -1638,6 +1651,11 @@
"configurePreset": "portenta_c33"
},
{
+ "name": "py32f071_dev_board",
+ "description": "Build preset for the py32f071_dev_board board",
+ "configurePreset": "py32f071_dev_board"
+ },
+ {
"name": "pybadge",
"description": "Build preset for the pybadge board",
"configurePreset": "pybadge"
@@ -2258,6 +2276,19 @@
]
},
{
+ "name": "apm32f072_dev_board",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "apm32f072_dev_board"
+ },
+ {
+ "type": "build",
+ "name": "apm32f072_dev_board"
+ }
+ ]
+ },
+ {
"name": "arduino_nano33_ble",
"steps": [
{
@@ -3896,6 +3927,19 @@
]
},
{
+ "name": "py32f071_dev_board",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "py32f071_dev_board"
+ },
+ {
+ "type": "build",
+ "name": "py32f071_dev_board"
+ }
+ ]
+ },
+ {
"name": "pybadge",
"steps": [
{
diff --git a/hw/bsp/apm32f0xx/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/apm32f0xx/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..b8d555ebe
--- /dev/null
+++ b/hw/bsp/apm32f0xx/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 "apm32f0xx.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/apm32f0xx/boards/apm32f072_dev_board/board.cmake b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake
new file mode 100644
index 000000000..d25f675be
--- /dev/null
+++ b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.cmake
@@ -0,0 +1,13 @@
+set(MCU_VARIANT APM32F072xB)
+set(MCU_LINKER_NAME APM32F07xxB)
+
+set(JLINK_DEVICE APM32F072RB)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ ${MCU_VARIANT}
+ CFG_EXAMPLE_MSC_READONLY
+ CFG_EXAMPLE_MSC_DUAL_READONLY
+ CFG_EXAMPLE_VIDEO_READONLY
+ )
+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 000000000..2c9e567e5
--- /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 000000000..f78d2091f
--- /dev/null
+++ b/hw/bsp/apm32f0xx/boards/apm32f072_dev_board/board.mk
@@ -0,0 +1,10 @@
+MCU_VARIANT = APM32F072xB
+MCU_LINKER_NAME = APM32F07xxB
+
+JLINK_DEVICE = APM32F072RB
+
+CFLAGS += \
+ -D${MCU_VARIANT} \
+ -DCFG_EXAMPLE_MSC_READONLY \
+ -DCFG_EXAMPLE_MSC_DUAL_READONLY \
+ -DCFG_EXAMPLE_VIDEO_READONLY
diff --git a/hw/bsp/apm32f0xx/family.c b/hw/bsp/apm32f0xx/family.c
new file mode 100644
index 000000000..643490797
--- /dev/null
+++ b/hw/bsp/apm32f0xx/family.c
@@ -0,0 +1,146 @@
+/*
+ * 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 "bsp/board_api.h"
+#include "board.h"
+
+void USBD_IRQHandler(void);
+#if CFG_TUSB_OS == OPT_OS_NONE
+void SysTick_Handler(void);
+void SVC_Handler(void);
+void PendSV_Handler(void);
+#endif
+void HardFault_Handler(void);
+void _init(void);
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USBD_IRQHandler(void) {
+ tud_int_handler(0);
+}
+
+//--------------------------------------------------------------------+
+// Board Init
+//--------------------------------------------------------------------+
+void board_init(void) {
+ // Configure HSE and PLL for a 48 MHz system clock
+ SystemClockConfig();
+
+ // Route the 48 MHz PLL clock to USB
+ RCM_ConfigUSBCLK(RCM_USBCLK_PLLCLK);
+
+ // 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 000000000..199ba7cb5
--- /dev/null
+++ b/hw/bsp/apm32f0xx/family.cmake
@@ -0,0 +1,83 @@
+include_guard()
+
+set(APM32_FAMILY apm32f0xx)
+set(APM32_SDK ${TOP}/hw/mcu/geehy/APM32F0xx_SDK/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
+ )
+ 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 000000000..7e26918c2
--- /dev/null
+++ b/hw/bsp/apm32f0xx/family.mk
@@ -0,0 +1,38 @@
+APM32_FAMILY = apm32f0xx
+APM32_SDK = hw/mcu/geehy/APM32F0xx_SDK/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)/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/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake
index fb9ccb3a3..287b8c2ff 100644
--- a/hw/bsp/ch32v10x/family.cmake
+++ b/hw/bsp/ch32v10x/family.cmake
@@ -93,6 +93,6 @@ function(family_configure_example TARGET RTOS)
# Flashing
family_add_bin_hex(${TARGET})
- family_flash_openocd_wch(${TARGET})
+ family_flash_openocd(${TARGET})
#family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
endfunction()
diff --git a/hw/bsp/ch32v10x/family.mk b/hw/bsp/ch32v10x/family.mk
index fb699b0bb..443509699 100644
--- a/hw/bsp/ch32v10x/family.mk
+++ b/hw/bsp/ch32v10x/family.mk
@@ -49,5 +49,5 @@ INC += \
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
-OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+OPENOCD_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-openocd-wch
diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c
index 76024cfde..8875e4faa 100644
--- a/hw/bsp/ch32v20x/family.c
+++ b/hw/bsp/ch32v20x/family.c
@@ -27,25 +27,25 @@ manufacturer: WCH
* - CFG_TUD_WCH_USBIP_USBFS
*/
-// Port0: 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
-}
+// Port0: USBD (fsdev). The USBD raises three IRQ lines (LP/HP/WakeUp) that all funnel into the
+// non-reentrant tud_int_handler and can nest (HP preempts LP) with QingKe HWSTK enabled. The
+// mainline toolchain's plain __attribute__((interrupt)) emits a software prologue that fights the
+// hardware context stack and corrupts the return on nesting. Emit naked handlers that rely on
+// HWSTK for context save/restore (equivalent to WCH's "WCH-Interrupt-fast"), which nests safely.
+#if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_FSDEV
+ // The `call dcd_int_handler` below lives inside naked asm where LTO cannot see it; without a
+ // compiler-visible reference, -flto builds (make) internalize/drop the symbol and the link fails.
+ TU_ATTR_USED static void (*const fsdev_isr_keep)(uint8_t) = dcd_int_handler;
+ #define FSDEV_NAKED_ISR(name) \
+ __attribute__((naked)) __attribute__((used)) void name(void) { \
+ __asm volatile("li a0, 0\n\t call dcd_int_handler\n\t mret"); }
+#else
+ #define FSDEV_NAKED_ISR(name) \
+ __attribute__((naked)) __attribute__((used)) void name(void) { __asm volatile("mret"); }
+#endif
+FSDEV_NAKED_ISR(USB_LP_CAN1_RX0_IRQHandler)
+FSDEV_NAKED_ISR(USB_HP_CAN1_TX_IRQHandler)
+FSDEV_NAKED_ISR(USBWakeUp_IRQHandler)
// Port1: USBFS
__attribute__((interrupt)) __attribute__((used)) void USBHD_IRQHandler(void) {
diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake
index 785f5ee35..a27ff021e 100644
--- a/hw/bsp/ch32v20x/family.cmake
+++ b/hw/bsp/ch32v20x/family.cmake
@@ -125,7 +125,7 @@ function(family_configure_example TARGET RTOS)
# Flashing
family_add_bin_hex(${TARGET})
- family_flash_openocd_wch(${TARGET})
+ family_flash_openocd(${TARGET})
family_flash_wlink_rs(${TARGET})
#family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
endfunction()
diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk
index 1d059bcba..1889c4e26 100644
--- a/hw/bsp/ch32v20x/family.mk
+++ b/hw/bsp/ch32v20x/family.mk
@@ -63,6 +63,6 @@ INC += \
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
-OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+OPENOCD_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-wlink-rs
#flash: flash-openocd-wch
diff --git a/hw/bsp/ch32v30x/family.c b/hw/bsp/ch32v30x/family.c
index aee4e7d4f..02c3c7d44 100644
--- a/hw/bsp/ch32v30x/family.c
+++ b/hw/bsp/ch32v30x/family.c
@@ -29,6 +29,7 @@
*/
#include "stdio.h"
+#include <string.h>
// https://github.com/openwch/ch32v307/pull/90
// https://github.com/openwch/ch32v20x/pull/12
@@ -166,6 +167,14 @@ uint32_t board_button_read(void) {
#endif
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ volatile uint32_t* ch32_uuid = ((volatile uint32_t*) 0x1FFFF7E8UL); // ESIG unique ID
+ uint32_t uid[3] = { ch32_uuid[0], ch32_uuid[1], ch32_uuid[2] };
+ const size_t len = max_len < sizeof(uid) ? max_len : sizeof(uid);
+ memcpy(id, uid, len); // byte copy: id[] need not be 4-byte aligned
+ return len;
+}
+
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
diff --git a/hw/bsp/ch32v30x/family.cmake b/hw/bsp/ch32v30x/family.cmake
index b974bd5e7..e33e4b85d 100644
--- a/hw/bsp/ch32v30x/family.cmake
+++ b/hw/bsp/ch32v30x/family.cmake
@@ -115,6 +115,6 @@ function(family_configure_example TARGET RTOS)
# Flashing
family_add_bin_hex(${TARGET})
- family_flash_openocd_wch(${TARGET})
+ family_flash_openocd(${TARGET})
family_flash_wlink_rs(${TARGET})
endfunction()
diff --git a/hw/bsp/ch32v30x/family.mk b/hw/bsp/ch32v30x/family.mk
index 5ccdea8ae..59778ec54 100644
--- a/hw/bsp/ch32v30x/family.mk
+++ b/hw/bsp/ch32v30x/family.mk
@@ -62,5 +62,5 @@ LD_FILE ?= $(FAMILY_PATH)/linker/ch32v30x.ld
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
-OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+OPENOCD_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-openocd-wch
diff --git a/hw/bsp/ch583/family.cmake b/hw/bsp/ch583/family.cmake
index a379298e5..f4b874e4e 100644
--- a/hw/bsp/ch583/family.cmake
+++ b/hw/bsp/ch583/family.cmake
@@ -104,5 +104,5 @@ function(family_configure_example TARGET RTOS)
# Flashing
family_add_bin_hex(${TARGET})
- family_flash_openocd_wch(${TARGET})
+ family_flash_openocd(${TARGET})
endfunction()
diff --git a/hw/bsp/ch583/family.mk b/hw/bsp/ch583/family.mk
index 98d0f9337..3444c4811 100644
--- a/hw/bsp/ch583/family.mk
+++ b/hw/bsp/ch583/family.mk
@@ -52,7 +52,7 @@ INC += \
LD_FILE ?= $(FAMILY_PATH)/linker/ch582.ld
-OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+OPENOCD_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-openocd-wch
# For freeRTOS port source
diff --git a/hw/bsp/ch583/wch-riscv.cfg b/hw/bsp/ch583/wch-riscv.cfg
index 64d595d8e..aa35aa9c5 100644
--- a/hw/bsp/ch583/wch-riscv.cfg
+++ b/hw/bsp/ch583/wch-riscv.cfg
@@ -9,7 +9,7 @@ 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 0x8000 -work-area-backup 1
+$_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
diff --git a/hw/bsp/family_rules.mk b/hw/bsp/family_rules.mk
index ccf49dd0e..011572888 100644
--- a/hw/bsp/family_rules.mk
+++ b/hw/bsp/family_rules.mk
@@ -130,20 +130,18 @@ flash-pyocd: $(BUILD)/$(PROJECT).hex
#pyocd reset -t $(PYOCD_TARGET)
# --------------- openocd -----------------
+# OPENOCD can name another build, e.g. one of the vendor forks, though
+# https://github.com/hathach/openocd branch tinyusb covers every board here
+OPENOCD ?= openocd
OPENOCD_OPTION ?=
flash-openocd: $(BUILD)/$(PROJECT).elf
- openocd $(OPENOCD_OPTION) -c "program $< verify reset exit"
+ $(OPENOCD) $(OPENOCD_OPTION) -c "program $< verify reset exit"
# --------------- 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 ?=
+# WCH parts need an openocd built with the wlinke adapter. The image is written
+# without verify: WCH code flash is not readable back over the debug bus.
flash-openocd-wch: $(BUILD)/$(PROJECT).elf
- $(OPENOCD_WCH) $(OPENOCD_WCH_OPTION) -c init -c halt -c "flash write_image $<" -c reset -c exit
+ $(OPENOCD) $(OPENOCD_OPTION) -c init -c halt -c "flash write_image $<" -c reset -c exit
# --------------- wlink-rs -----------------
# flash with https://github.com/ch32-rs/wlink
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index 1f3952205..33ceb49c2 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -688,7 +688,9 @@ function(family_flash_stflash TARGET)
endfunction()
-# Add flash openocd target
+# Add flash openocd target.
+# The default 'openocd' should be https://github.com/hathach/openocd (branch tinyusb): which is mainline plus
+# every config the rig needs (RP2350, MAX32/MAX78, WCH) and a drop-in superset of the vendor (downstream) forks
function(family_flash_openocd TARGET)
if (NOT DEFINED OPENOCD)
set(OPENOCD openocd)
@@ -715,38 +717,20 @@ function(family_flash_openocd TARGET)
#set_property(TARGET ${TARGET}-openocd PROPERTY FOLDER ${TARGET}-group)
endfunction()
-
-# 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)
+# Add flash openocd adi (Analog Devices) target using the openocd included
+# with msdk (MAXIM_PATH), otherwise the default openocd
+function(family_flash_openocd_adi TARGET)
+ # use openocd from msdk if MAXIM_PATH is set, as cmake variable or in the
+ # environment. Normalize the latter since msdk can be Windows (MinGW) or Linux
+ if (NOT DEFINED MAXIM_PATH AND DEFINED ENV{MAXIM_PATH})
+ file(TO_CMAKE_PATH "$ENV{MAXIM_PATH}" MAXIM_PATH)
endif ()
- family_flash_openocd(${TARGET})
-endfunction()
-
-
-# Add flash openocd adi (Analog Devices) target
-# included with msdk or compiled from release branch of https://github.com/analogdevicesinc/openocd
-function(family_flash_openocd_adi TARGET)
- if (DEFINED MAXIM_PATH)
- # use openocd from msdk with MAXIM_PATH cmake variable first if the user specified it
- set(OPENOCD ${MAXIM_PATH}/Tools/OpenOCD/openocd)
- set(OPENOCD_OPTION2 "-s ${MAXIM_PATH}/Tools/OpenOCD/scripts")
- elseif (DEFINED ENV{MAXIM_PATH})
- # use openocd from msdk with MAXIM_PATH environment variable. Normalize
- # since msdk can be Windows (MinGW) or Linux
- file(TO_CMAKE_PATH "$ENV{MAXIM_PATH}" MAXIM_PATH_NORM)
- set(OPENOCD ${MAXIM_PATH_NORM}/Tools/OpenOCD/openocd)
- set(OPENOCD_OPTION2 "-s ${MAXIM_PATH_NORM}/Tools/OpenOCD/scripts")
- else()
- # compiled from source
- if (NOT DEFINED OPENOCD_ADI_PATH)
- set(OPENOCD_ADI_PATH $ENV{HOME}/app/openocd_adi)
+ if (MAXIM_PATH)
+ if (NOT DEFINED OPENOCD)
+ set(OPENOCD ${MAXIM_PATH}/Tools/OpenOCD/openocd)
endif ()
- set(OPENOCD ${OPENOCD_ADI_PATH}/src/openocd)
- set(OPENOCD_OPTION2 "-s ${OPENOCD_ADI_PATH}/tcl")
+ set(OPENOCD_OPTION2 "-s ${MAXIM_PATH}/Tools/OpenOCD/scripts")
endif ()
family_flash_openocd(${TARGET})
diff --git a/hw/bsp/imxrt/boards/metro_m7_1011/ozone/metro_m7_1011.jdebug b/hw/bsp/imxrt/boards/metro_m7_1011/ozone/metro_m7_1011.jdebug
index 90f9b77e5..80489b61c 100644
--- a/hw/bsp/imxrt/boards/metro_m7_1011/ozone/metro_m7_1011.jdebug
+++ b/hw/bsp/imxrt/boards/metro_m7_1011/ozone/metro_m7_1011.jdebug
@@ -10,6 +10,7 @@
*/
void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
Project.SetTraceTiming (50, 50, 50, 50);
Project.SetDevice ("MIMXRT1011xxx4A");
Project.SetHostIF ("USB", "");
@@ -22,7 +23,7 @@ void OnProjectLoad (void) {
// timing delay for trace pins in pico seconds, default is 2 nano seconds
- File.Open ("../../../../../../examples/cmake-build-metro-m7-1011-sd/device/cdc_msc/cdc_msc.elf");
+ File.Open ("../../../../../../examples/cmake-build-metro_m7_1011/device/cdc_msc/cdc_msc.elf");
}
/*********************************************************************
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h
index a6332d896..c041fd47b 100644
--- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h
@@ -35,6 +35,11 @@
// required since iMXRT MCUX-SDK include this file for board size
#define BOARD_FLASH_SIZE (0x1000000U)
+// TRACE_ETM: this board wires the 100M PHY reset (ENET_RST_B) to
+// GPIO_LPSR_04; the family trace init holds it in reset (RMII lines share
+// the trace pads)
+#define TRACE_ETM_QUIET_ENET_PHY 1
+
// LED: IOMUXC_GPIO_AD_04_GPIO9_IO03
#define LED_PORT BOARD_INITPINS_USER_LED_PERIPHERAL
#define LED_PIN BOARD_INITPINS_USER_LED_CHANNEL
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176.jdebug b/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176.jdebug
new file mode 100644
index 000000000..6931b9cd1
--- /dev/null
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176.jdebug
@@ -0,0 +1,69 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* MIMXRT1170-EVKB trace requires board rework: the TRACE pads
+* (GPIO_DISP_B2_02..06) are factory-wired to the ENET_1G PHY - populate
+* 0-ohm R1881-R1886 to route them to the Cortex Debug+ETM connector J58
+* (EVKB Hardware User Guide 3.2).
+* Firmware must be built with TRACE_ETM=1 (trace pad mux + CSTRACE clock
+* + JTAG_nTRST/DMIC_DATA1 pad fix in board_init).
+*
+* Validated: port width 1, 0 ns sample timing, 50 MHz CSTRACE root
+* (25 MHz TRACE_CLK pin, set by trace_etm_init - the rework path corrupts
+* at the stock 132 MHz root) while the CM7 runs 996 MHz. A startup-burst
+* trace overflow is expected and benign; width 4 fails at any timing.
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ // declares the CSSYS TPIU/funnel (system APB-AP, not in the CM7 ROM table)
+ Project.SetJLinkScript ("./mimxrt1176_trace.JLinkScript");
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (1);
+ Project.SetTraceTiming (0, 0, 0, 0);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 996000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M7F.svd");
+
+ Project.SetDevice ("MIMXRT1176xxxA_M7");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-mimxrt1170_evkb/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* JTAG_nTRST shares its pad with DMIC_DATA1, which drives it low by
+* default and kills ETM trace - mux the pad to GPIO before the app runs
+* (EVKB Hardware User Guide 3.2). No SP/PC init here: the app boots from
+* FlexSPI NOR, so the ROM bootloader must perform it (SEGGER wiki
+* "i.MXRT1176" / NXP community solution for ERR050708 boards).
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ Target.WriteU32 (0x40C08028, 0xA); // IOMUXC GPIO_LPSR_10 -> GPIO12_IO10
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Intentionally empty: SP/PC init from the vector table would bypass the
+* ROM bootloader's FlexSPI setup (see AfterTargetReset note).
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+}
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176_trace.JLinkScript b/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176_trace.JLinkScript
new file mode 100644
index 000000000..ef39235d8
--- /dev/null
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/ozone/mimxrt1176_trace.JLinkScript
@@ -0,0 +1,11 @@
+/* RT1176 pin trace: the CSSYS TPIU and ATB funnel live on the system APB-AP
+ * (AP2) and are not discoverable from the CM7 ROM table - declare them, or
+ * J-Link aborts with "Required trace components for pin trace not found!"
+ * (addresses per i.MX RT1170 RM memory map: CSSYS TPIU E004_6000, CSSYS ATB
+ * Funnel E004_5000; same values as SEGGER's RT1176 trace example script).
+ */
+int ConfigTargetSettings(void) {
+ JLINK_ExecCommand("CORESIGHT_SetTPIUBaseAddr = 0xE0046000 ForceUnlock = 1 APIndex = 2");
+ JLINK_ExecCommand("CORESIGHT_SetCSTFBaseAddr = 0xE0045000 ForceUnlock = 1 APIndex = 2");
+ return 0;
+}
diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c
index 9f3297e9a..4bd7993f0 100644
--- a/hw/bsp/imxrt/family.c
+++ b/hw/bsp/imxrt/family.c
@@ -106,6 +106,74 @@ static void init_usb_phy(uint8_t usb_id) {
usb_phy->TX = phytx;
}
+#ifdef TRACE_ETM
+static void trace_etm_init(void) {
+#if defined(CPU_MIMXRT1011DAE5A)
+ // Metro M7 rev A "ETM Trace" rework: 4-bit TRACE + TRACE_CLK on the added
+ // 2x10 header; the RT1011 has a single mux option per trace signal
+ IOMUXC_SetPinMux(IOMUXC_GPIO_AD_00_ARM_TRACE0, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_13_ARM_TRACE1, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_12_ARM_TRACE2, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_11_ARM_TRACE3, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_AD_02_ARM_TRACE_CLK, 0U);
+ // fast slew, max speed, high drive
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_00_ARM_TRACE0, 0x00F1U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_13_ARM_TRACE1, 0x00F1U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_12_ARM_TRACE2, 0x00F1U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_11_ARM_TRACE3, 0x00F1U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_02_ARM_TRACE_CLK, 0x00F1U);
+
+ // TRACE_CLK_ROOT already runs 132 MHz (PLL2/4) from BOARD_BootClockRUN,
+ // which leaves it gated - just ungate
+ CLOCK_EnableClock(kCLOCK_Trace);
+#elif defined(CPU_MIMXRT1176DVMAA_cm7)
+ // JTAG_nTRST pad is shared with DMIC_DATA1 which drives it low by default and
+ // breaks ETM trace - switch the pad to GPIO (MIMXRT1170-EVKB HUG 3.2)
+ IOMUXC_SetPinMux(IOMUXC_GPIO_LPSR_10_GPIO12_IO10, 0U);
+
+#ifdef TRACE_ETM_QUIET_ENET_PHY
+ // Hold the 100M Ethernet PHY (RTL8201) in reset: its RMII lines are
+ // hardwired to the trace pads and drive against the stream at speed. The
+ // reset net is a BOARD property (mimxrt1170_evkb: ENET_RST_B =
+ // GPIO_LPSR_04), hence the board.h gate.
+ IOMUXC_SetPinMux(IOMUXC_GPIO_LPSR_04_GPIO12_IO04, 0U);
+ GPIO12->GDIR |= (1U << 4);
+ GPIO12->DR &= ~(1U << 4);
+#endif
+
+ // TRACE0-3 + TRACE_CLK on GPIO_DISP_B2_02..06, fast slew + high drive
+ IOMUXC_SetPinMux(IOMUXC_GPIO_DISP_B2_02_ARM_TRACE00, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_DISP_B2_03_ARM_TRACE01, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_DISP_B2_04_ARM_TRACE02, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_DISP_B2_05_ARM_TRACE03, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_DISP_B2_06_ARM_TRACE_CLK, 0U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_DISP_B2_02_ARM_TRACE00, IOMUXC_SW_PAD_CTL_PAD_DSE_MASK);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_DISP_B2_03_ARM_TRACE01, IOMUXC_SW_PAD_CTL_PAD_DSE_MASK);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_DISP_B2_04_ARM_TRACE02, IOMUXC_SW_PAD_CTL_PAD_DSE_MASK);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_DISP_B2_05_ARM_TRACE03, IOMUXC_SW_PAD_CTL_PAD_DSE_MASK);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_DISP_B2_06_ARM_TRACE_CLK, IOMUXC_SW_PAD_CTL_PAD_DSE_MASK);
+
+ // 100 MHz CSTRACE root (OscRc400M/4) -> 50 MHz TRACE_CLK pin (= root/2).
+ // With the PHY held in reset the CLK line is clean here; 133 MHz root
+ // (66 MHz pin) is marginal on this board, stock 132 MHz corrupts.
+ CLOCK_SetRootClockMux(kCLOCK_Root_Cstrace, kCLOCK_CSTRACE_ClockRoot_MuxOscRc400M);
+ CLOCK_SetRootClockDiv(kCLOCK_Root_Cstrace, 4);
+ CLOCK_EnableClock(kCLOCK_Cstrace);
+
+ // Enable the CM7 slave port on the platform trace funnel (E004_3000): the
+ // debugger only programs the CSSYS funnel/TPIU it was told about, and this
+ // in-between funnel resets with all ports disabled, silently eating the ETM
+ // stream. Core-side CoreSight accesses honor the lock, hence the LAR unlock.
+ *(volatile uint32_t *) 0xE0043FB0 = 0xC5ACCE55;
+ *(volatile uint32_t *) 0xE0043000 |= 1U;
+#else
+ #error "TRACE_ETM: no trace pin setup for this MCU variant"
+#endif
+}
+#else
+ #define trace_etm_init()
+#endif
+
void board_init(void) {
// make sure the dcache is on.
#if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT
@@ -119,10 +187,7 @@ void board_init(void) {
SystemCoreClockUpdate();
BOARD_ConfigMPU(); // defined in board.h
-
-#ifdef TRACE_ETM
- //CLOCK_EnableClock(kCLOCK_Trace);
-#endif
+ trace_etm_init();
#if CFG_TUSB_OS == OPT_OS_NONE
// 1ms tick timer
diff --git a/hw/bsp/kinetis_k/family.c b/hw/bsp/kinetis_k/family.c
index a5af83931..2df3313b8 100644
--- a/hw/bsp/kinetis_k/family.c
+++ b/hw/bsp/kinetis_k/family.c
@@ -35,10 +35,25 @@
#include "fsl_clock.h"
#include "fsl_uart.h"
#include "fsl_sysmpu.h"
+#include "common/tusb_fifo.h"
#include "board/clock_config.h"
#include "board/pin_mux.h"
+#ifdef UART_DEV
+// RX ring buffer filled by the RDRF interrupt so board_uart_read() is non-blocking
+// and does not drop bytes to UART overrun (see stm32 family for reference).
+static uint8_t uart_rx_ff_buf[32];
+static tu_fifo_t uart_rx_ff;
+
+void UART0_RX_TX_IRQHandler(void) {
+ if (UART_DEV->S1 & UART_S1_RDRF_MASK) {
+ uint8_t byte = UART_DEV->D; // reading S1 then D clears RDRF (and any overrun)
+ tu_fifo_write(&uart_rx_ff, &byte);
+ }
+}
+#endif
+
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
@@ -89,6 +104,9 @@ void board_init(void) {
.enableRx = true
};
UART_Init(UART_DEV, &uart_config, UART_CLOCK);
+ tu_fifo_config(&uart_rx_ff, uart_rx_ff_buf, sizeof(uart_rx_ff_buf), false);
+ UART_DEV->C2 |= UART_C2_RIE_MASK; // enable RX data register full interrupt
+ NVIC_EnableIRQ(UART0_RX_TX_IRQn);
#endif
// USB
@@ -112,14 +130,11 @@ uint32_t board_button_read(void) {
}
int board_uart_read(uint8_t *buf, int len) {
- (void) buf;
- (void) len;
#ifdef UART_DEV
- // Read blocking will block until there is data
-// UART_ReadBlocking(UART_DEV, buf, len);
-// return len;
- return 0;
+ return (int) tu_fifo_read_n(&uart_rx_ff, buf, (uint16_t) len);
#else
+ (void) buf;
+ (void) len;
return 0;
#endif
}
@@ -144,6 +159,19 @@ int board_uart_write(void const *buf, int len) {
#endif
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ (void) max_len;
+ // Kinetis 128-bit Unique Identification Register (SIM->UIDH/UIDMH/UIDML/UIDL)
+ uint32_t* id32 = (uint32_t*) (uintptr_t) id;
+
+ id32[0] = SIM->UIDH;
+ id32[1] = SIM->UIDMH;
+ id32[2] = SIM->UIDML;
+ id32[3] = SIM->UIDL;
+
+ return 16;
+}
+
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
diff --git a/hw/bsp/kinetis_k/family.cmake b/hw/bsp/kinetis_k/family.cmake
index e1b5c221e..e408c0f4a 100644
--- a/hw/bsp/kinetis_k/family.cmake
+++ b/hw/bsp/kinetis_k/family.cmake
@@ -63,7 +63,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c
- ${TOP}/src/portable/nxp/khci/hcd_khci.c
+ ${TOP}/src/portable/chipidea/ci_fs/hcd_ci_fs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/kinetis_k/family.mk b/hw/bsp/kinetis_k/family.mk
index b1e1fb3aa..5d0e4a702 100644
--- a/hw/bsp/kinetis_k/family.mk
+++ b/hw/bsp/kinetis_k/family.mk
@@ -17,8 +17,8 @@ LDFLAGS += \
--specs=nosys.specs --specs=nano.specs \
SRC_C += \
- src/portable/nxp/khci/dcd_khci.c \
- src/portable/nxp/khci/hcd_khci.c \
+ src/portable/chipidea/ci_fs/dcd_ci_fs.c \
+ src/portable/chipidea/ci_fs/hcd_ci_fs.c \
$(MCU_DIR)/system_${MCU_VARIANT}.c \
$(MCU_DIR)/drivers/fsl_clock.c \
$(SDK_DIR)/drivers/gpio/fsl_gpio.c \
diff --git a/hw/bsp/kinetis_k32l/family.cmake b/hw/bsp/kinetis_k32l/family.cmake
index 020695589..950682363 100644
--- a/hw/bsp/kinetis_k32l/family.cmake
+++ b/hw/bsp/kinetis_k32l/family.cmake
@@ -64,8 +64,8 @@ function(family_configure_example TARGET RTOS)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
- ${TOP}/src/portable/nxp/khci/dcd_khci.c
- ${TOP}/src/portable/nxp/khci/hcd_khci.c
+ ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c
+ ${TOP}/src/portable/chipidea/ci_fs/hcd_ci_fs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/kinetis_k32l/family.mk b/hw/bsp/kinetis_k32l/family.mk
index a99fb5dbe..357128aa5 100644
--- a/hw/bsp/kinetis_k32l/family.mk
+++ b/hw/bsp/kinetis_k32l/family.mk
@@ -13,8 +13,8 @@ LDFLAGS += \
-specs=nosys.specs -specs=nano.specs
SRC_C += \
- src/portable/nxp/khci/dcd_khci.c \
- src/portable/nxp/khci/hcd_khci.c \
+ src/portable/chipidea/ci_fs/dcd_ci_fs.c \
+ src/portable/chipidea/ci_fs/hcd_ci_fs.c \
$(MCUX_DEVICES)/K32L/$(MCU_VARIANT)/system_$(MCU_VARIANT).c \
$(MCUX_DEVICES)/K32L/$(MCU_VARIANT)/drivers/fsl_clock.c \
$(MCUX_CORE)/drivers/gpio/fsl_gpio.c \
diff --git a/hw/bsp/kinetis_kl/family.cmake b/hw/bsp/kinetis_kl/family.cmake
index 230a3057d..b74f4f8b9 100644
--- a/hw/bsp/kinetis_kl/family.cmake
+++ b/hw/bsp/kinetis_kl/family.cmake
@@ -62,7 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c
- ${TOP}/src/portable/nxp/khci/hcd_khci.c
+ ${TOP}/src/portable/chipidea/ci_fs/hcd_ci_fs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/kinetis_kl/family.mk b/hw/bsp/kinetis_kl/family.mk
index 201ab99dc..9c780a868 100644
--- a/hw/bsp/kinetis_kl/family.mk
+++ b/hw/bsp/kinetis_kl/family.mk
@@ -17,8 +17,8 @@ LDFLAGS += \
-specs=nosys.specs -specs=nano.specs \
SRC_C += \
- src/portable/nxp/khci/dcd_khci.c \
- src/portable/nxp/khci/hcd_khci.c \
+ src/portable/chipidea/ci_fs/dcd_ci_fs.c \
+ src/portable/chipidea/ci_fs/hcd_ci_fs.c \
$(MCU_DIR)/system_$(MCU).c \
$(MCU_DIR)/drivers/fsl_clock.c \
$(SDK_DIR)/drivers/gpio/fsl_gpio.c \
diff --git a/hw/bsp/lpc11/boards/lpcxpresso11u37/board.mk b/hw/bsp/lpc11/boards/lpcxpresso11u37/board.mk
index fdc17374b..718c46bbf 100644
--- a/hw/bsp/lpc11/boards/lpcxpresso11u37/board.mk
+++ b/hw/bsp/lpc11/boards/lpcxpresso11u37/board.mk
@@ -4,8 +4,7 @@ MCU_DRV = 11xx
CFLAGS += \
-DCORE_M0 \
-DCFG_EXAMPLE_MSC_READONLY \
- -DCFG_EXAMPLE_VIDEO_READONLY \
- -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))'
+ -DCFG_EXAMPLE_VIDEO_READONLY
# mcu driver cause following warnings
CFLAGS += \
diff --git a/hw/bsp/lpc11/boards/lpcxpresso11u37/lpc11u37.ld b/hw/bsp/lpc11/boards/lpcxpresso11u37/lpc11u37.ld
index 8e0a4e4c6..b7237a3ec 100644
--- a/hw/bsp/lpc11/boards/lpcxpresso11u37/lpc11u37.ld
+++ b/hw/bsp/lpc11/boards/lpcxpresso11u37/lpc11u37.ld
@@ -172,6 +172,22 @@ SECTIONS
. = ALIGN(4) ;
_end_noinit = .;
} > RamLoc8
+ /* Main (MSP/ISR) stack lives at the top of the USB SRAM bank: the 8K main bank is packed so
+ tight that only ~280 B remained above .bss, and ISR frames overflowed into the topmost task
+ stack (cdc_msc_freertos hard fault). Nothing else is placed in this bank in either build
+ system, so the stack owns all 2 KB; the ASSERT is future-proofing in case USB buffers are
+ ever mapped here again.
+
+ This bank is clocked by SYSAHBCLKCTRL[27] (USBRAM enable), and the stack is used from the
+ first instruction of the reset handler - long before any TinyUSB or BSP code could turn a
+ clock on. It works because the boot ROM hands over with that bit already set. Anything that
+ gates the USB RAM clock to save power will hard fault at reset, not at USB init. */
+ __user_stack_top = ORIGIN(RamUsb2) + LENGTH(RamUsb2);
+ /* Stated as an addition, not a subtraction: ld arithmetic is unsigned, so an overflowing
+ bank would underflow the difference into a huge positive value and pass silently. */
+ ASSERT(ADDR(.noinit_RAM2) + SIZEOF(.noinit_RAM2) + 0x200 <= __user_stack_top,
+ "main stack headroom in RamUsb2 below 512 bytes")
+
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc8 - 0);
diff --git a/hw/bsp/lpc15/family.c b/hw/bsp/lpc15/family.c
index bbfee1b51..5178ad68b 100644
--- a/hw/bsp/lpc15/family.c
+++ b/hw/bsp/lpc15/family.c
@@ -122,6 +122,19 @@ uint32_t board_button_read(void)
return Chip_GPIO_GetPinState(LPC_GPIO, BUTTON_PORT, BUTTON_PIN) ? 0 : 1;
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len)
+{
+ // IAP ReadUID (cmd 58) returns status + 4 words = full 128-bit UID
+ unsigned int command[5] = { IAP_READ_UID_CMD, 0, 0, 0, 0 };
+ unsigned int result[5];
+ iap_entry(command, result);
+ TU_ASSERT(result[0] == IAP_CMD_SUCCESS, 0);
+
+ size_t const len = tu_min32(max_len, 16);
+ memcpy(id, &result[1], len);
+ return len;
+}
+
int board_uart_read(uint8_t* buf, int len)
{
(void) buf; (void) len;
diff --git a/hw/bsp/lpc18/boards/lpcxpresso18s37/board.h b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.h
index 2cf4dbdf8..1be07c49e 100644
--- a/hw/bsp/lpc18/boards/lpcxpresso18s37/board.h
+++ b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.h
@@ -76,6 +76,12 @@ static inline void board_lpc18_pinmux(void)
Chip_SCU_SetPinMuxing(pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T));
}
+
+// TRACE_ETM builds: no trace header is wired out on the LPCXpresso18S37 -
+// provide the no-op the family init expects (see mcb1800/ea4357 for a
+// board that routes the trace pins)
+static inline void board_trace_pinmux(void) {}
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/lpc18/boards/mcb1800/board.h b/hw/bsp/lpc18/boards/mcb1800/board.h
index dba7a62a3..ec7f1fa95 100644
--- a/hw/bsp/lpc18/boards/mcb1800/board.h
+++ b/hw/bsp/lpc18/boards/mcb1800/board.h
@@ -48,15 +48,6 @@
static inline void board_lpc18_pinmux(void) {
const PINMUX_GRP_T pinmuxing[] = {
- // ETM Trace
- #ifdef TRACE_ETM
- { 0xF, 4, SCU_MODE_FUNC2 | SCU_MODE_HIGHSPEEDSLEW_EN },
- { 0xF, 5, SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
- { 0xF, 6, SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
- { 0xF, 7, SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
- { 0xF, 8, SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
- #endif
-
// LEDs
{ 0xD, 10, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4) },
{ 0xD, 11, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) },
@@ -96,6 +87,24 @@ static inline void board_lpc18_pinmux(void) {
}
}
+#ifdef TRACE_ETM
+// Must run AFTER Chip_SetupCoreClock: muxing the trace pins earlier starts
+// TRACECLK at the boot clock and the mid-init frequency switch desyncs the
+// trace decoder ("Unknown trace data packet").
+static inline void board_trace_pinmux(void) {
+ // SCU_MODE_INACT: disable the pull-up on the 60 MHz trace lines - leaving it
+ // enabled degrades the edges enough for intermittent decode corruption.
+ const PINMUX_GRP_T trace_pinmux[] = {
+ { 0xF, 4, SCU_MODE_INACT | SCU_MODE_FUNC2 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 5, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 6, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 7, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 8, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ };
+ Chip_SCU_SetPinMuxing(trace_pinmux, sizeof(trace_pinmux) / sizeof(PINMUX_GRP_T));
+}
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug b/hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug
index f94960f09..a6dcef0eb 100644
--- a/hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug
+++ b/hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug
@@ -10,7 +10,7 @@
*/
void OnProjectLoad (void) {
Project.AddSvdFile ("Cortex-M3.svd");
- Project.AddSvdFile ("../../../../../../../cmsis-svd/data/NXP/LPC18xx.svd");
+ //Project.AddSvdFile ("../../../../../../../cmsis-svd/data/NXP/LPC18xx.svd");
Project.SetDevice ("LPC1857");
Project.SetHostIF ("USB", "");
@@ -20,8 +20,8 @@ void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
Project.SetTracePortWidth (4);
- //File.Open ("../../../../../../examples/cmake-build-mcb1800/device/cdc_msc/cdc_msc.elf");
- File.Open ("../../../../../../examples/cmake-build-mcb1800/host/cdc_msc_hid/cdc_msc_hid.elf");
+ File.Open ("../../../../../../examples/cmake-build-mcb1800/device/cdc_msc/cdc_msc.elf");
+ //File.Open ("../../../../../../examples/cmake-build-mcb1800/host/cdc_msc_hid/cdc_msc_hid.elf");
}
/*********************************************************************
*
diff --git a/hw/bsp/lpc18/family.c b/hw/bsp/lpc18/family.c
index 8a612d9d8..58c2193fc 100644
--- a/hw/bsp/lpc18/family.c
+++ b/hw/bsp/lpc18/family.c
@@ -69,6 +69,7 @@ void SystemInit(void) {
#ifdef TRACE_ETM
// Trace clock is limited to 60MHz, limit CPU clock to 120MHz
Chip_SetupCoreClock(CLKIN_CRYSTAL, 120000000UL, true);
+ board_trace_pinmux(); // after clock setup so TRACECLK starts at its final frequency
#else
// CPU clock max to 180 Mhz
Chip_SetupCoreClock(CLKIN_CRYSTAL, MAX_CLOCK_FREQ, true);
diff --git a/hw/bsp/lpc40/boards/ea4088_quickstart/ozone/ea4088_quickstart.jdebug b/hw/bsp/lpc40/boards/ea4088_quickstart/ozone/ea4088_quickstart.jdebug
index 6aaf1076d..20de1e915 100644
--- a/hw/bsp/lpc40/boards/ea4088_quickstart/ozone/ea4088_quickstart.jdebug
+++ b/hw/bsp/lpc40/boards/ea4088_quickstart/ozone/ea4088_quickstart.jdebug
@@ -21,7 +21,7 @@ void OnProjectLoad (void) {
Project.SetTracePortWidth (4);
// User settings
- File.Open ("../../../../../../examples/device/cdc_msc/cmake-build-ea4088-quickstart/cdc_msc.elf");
+ File.Open ("../../../../../../examples/cmake-build-ea4088_quickstart/device/cdc_msc/cdc_msc.elf");
}
/*********************************************************************
diff --git a/hw/bsp/lpc40/family.c b/hw/bsp/lpc40/family.c
index d8a63576b..750bd2660 100644
--- a/hw/bsp/lpc40/family.c
+++ b/hw/bsp/lpc40/family.c
@@ -135,6 +135,19 @@ uint32_t board_button_read(void) {
return BUTTON_ACTIV_STATE == Chip_GPIO_GetPinState(LPC_GPIO, BUTTON_PORT, BUTTON_PIN);
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ // IAP ReadUID (cmd 58) returns status + 4 words = full 128-bit UID
+ // (lpcopen's Chip_IAP_ReadUID() only returns the first word)
+ unsigned int command[5] = { IAP_READ_UID_CMD, 0, 0, 0, 0 };
+ unsigned int result[5];
+ iap_entry(command, result);
+ TU_ASSERT(result[0] == IAP_CMD_SUCCESS, 0);
+
+ size_t const len = tu_min32(max_len, 16);
+ memcpy(id, &result[1], len);
+ return len;
+}
+
int board_uart_read(uint8_t *buf, int len) {
//return UART_ReceiveByte(BOARD_UART_PORT);
(void) buf;
diff --git a/hw/bsp/lpc43/boards/ea4357/board.h b/hw/bsp/lpc43/boards/ea4357/board.h
index fca617361..0152825f5 100644
--- a/hw/bsp/lpc43/boards/ea4357/board.h
+++ b/hw/bsp/lpc43/boards/ea4357/board.h
@@ -83,6 +83,22 @@ static const PINMUX_GRP_T pinmuxing[] = {
// { 0, 3, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0 },
//};
+#ifdef TRACE_ETM
+// Must run AFTER Chip_SetupCoreClock: muxing the trace pins earlier starts
+// TRACECLK at the boot clock and the mid-init frequency switch desyncs the
+// trace decoder. SCU_MODE_INACT keeps pull-ups off the 60 MHz lines.
+static inline void board_trace_pinmux(void) {
+ const PINMUX_GRP_T trace_pinmux[] = {
+ { 0xF, 4, SCU_MODE_INACT | SCU_MODE_FUNC2 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 5, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 6, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 7, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ { 0xF, 8, SCU_MODE_INACT | SCU_MODE_FUNC3 | SCU_MODE_HIGHSPEEDSLEW_EN },
+ };
+ Chip_SCU_SetPinMuxing(trace_pinmux, sizeof(trace_pinmux) / sizeof(PINMUX_GRP_T));
+}
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/lpc43/boards/lpcxpresso43s67/board.h b/hw/bsp/lpc43/boards/lpcxpresso43s67/board.h
index 4427905e8..6a317b5dc 100644
--- a/hw/bsp/lpc43/boards/lpcxpresso43s67/board.h
+++ b/hw/bsp/lpc43/boards/lpcxpresso43s67/board.h
@@ -71,6 +71,12 @@ static const PINMUX_GRP_T pinmuxing[] = {
{0x2, 5, SCU_MODE_INBUFF_EN | SCU_MODE_PULLUP | SCU_MODE_FUNC4 },
};
+
+// TRACE_ETM builds: no trace header is wired out on the LPCXpresso43S67 -
+// provide the no-op the family init expects (see mcb1800/ea4357 for a
+// board that routes the trace pins)
+static inline void board_trace_pinmux(void) {}
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/lpc43/family.c b/hw/bsp/lpc43/family.c
index 5aff49704..7f0722a33 100644
--- a/hw/bsp/lpc43/family.c
+++ b/hw/bsp/lpc43/family.c
@@ -59,6 +59,30 @@ void SystemInit(void);
// Invoked by startup code
void SystemInit(void)
{
+#if defined(__ICCARM__) && !defined(DONT_RESET_ON_RESTART)
+ __disable_irq();
+#endif
+
+ if (Chip_CREG_OnChipFlashIsPresent()) {
+ // The boot ROM configures flash for its 96 MHz clock, and debugger core
+ // resets can preserve it. Use safe timing before switching the M4 to 204 MHz.
+ Chip_CREG_SetFLASHAccess(FLASHTIM_SAFE_SETTING);
+ __DSB();
+ __ISB();
+ }
+
+#if defined(__ICCARM__) && !defined(DONT_RESET_ON_RESTART)
+ // A debugger restart resets the M4 core, but can leave LPC43 peripherals and
+ // pending interrupts active. Match the GCC startup sequence, which the IAR
+ // startup lacks, before the C runtime can reuse peripheral DMA memory.
+ LPC_RGU->RESET_CTRL[0] = 0x10DF1000u;
+ LPC_RGU->RESET_CTRL[1] = 0x01DFF7FFu;
+ for (uint32_t i = 0; i < 8; i++) {
+ NVIC->ICPR[i] = UINT32_MAX;
+ }
+ __enable_irq();
+#endif
+
#ifdef __USE_LPCOPEN
unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08;
@@ -89,7 +113,13 @@ void SystemInit(void)
// Chip_SCU_ClockPinMuxSet(pinclockmuxing[i].pinnum, pinclockmuxing[i].modefunc);
// }
+#ifdef TRACE_ETM
+ // Trace clock is limited to 60MHz, limit CPU clock to 120MHz
+ Chip_SetupCoreClock(CLKIN_CRYSTAL, 120000000UL, true);
+ board_trace_pinmux(); // after clock setup so TRACECLK starts at its final frequency
+#else
Chip_SetupXtalClocking();
+#endif
}
void board_init(void)
diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake
index b3d6ec722..d7992eec6 100644
--- a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake
+++ b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake
@@ -8,10 +8,6 @@ set(JLINK_OPTION "-USB 000727031389")
set(PYOCD_TARGET LPC55S28)
set(NXPLINK_DEVICE LPC55S28:LPCXpresso55S28)
-# device fullspeed, host highspeed
-set(RHPORT_DEVICE 0)
-set(RHPORT_HOST 1)
-
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
CPU_LPC55S28JBD100
diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.mk b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.mk
index db2e11fd7..aecb5a100 100644
--- a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.mk
+++ b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.mk
@@ -2,9 +2,9 @@ MCU_VARIANT = LPC55S28
MCU_CORE = LPC55S28
MCU_DRIVER_VARIANT = LPC55S69
-# device fullspeed, host highspeed
-RHPORT_DEVICE ?= 0
-RHPORT_HOST ?= 1
+# device highspeed, host fullspeed
+RHPORT_DEVICE ?= 1
+RHPORT_HOST ?= 0
CFLAGS += -DCPU_LPC55S28JBD100
diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c
index e021caf35..11bf86827 100644
--- a/hw/bsp/lpc55/family.c
+++ b/hw/bsp/lpc55/family.c
@@ -170,6 +170,14 @@ uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == GPIO_PinRead(GPIO, BUTTON_PORT, BUTTON_PIN);
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ // 128-bit UUID in the flash PFR region at 0x0009FC70 (UM11126 rev 2.1 section 48.8)
+ const uint8_t* uuid = (const uint8_t*) 0x0009FC70;
+ size_t const len = tu_min32(max_len, 16);
+ memcpy(id, uuid, len);
+ return len;
+}
+
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk
index a9b6f6af1..a640cc793 100644
--- a/hw/bsp/lpc55/family.mk
+++ b/hw/bsp/lpc55/family.mk
@@ -36,6 +36,8 @@ ifeq ($(RHPORT_HOST), 1)
SRC_C += $(TOP)/src/portable/nxp/lpc_ip3516/hcd_lpc_ip3516.c
else
CFLAGS += -DBOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED
+ # host on port 0 uses the OHCI controller (mirrors family.cmake)
+ SRC_C += $(TOP)/src/portable/ohci/ohci.c
endif
# mcu driver cause following warnings
diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake
index 89e2aadf2..b2b4fd45b 100644
--- a/hw/bsp/mcx/family.cmake
+++ b/hw/bsp/mcx/family.cmake
@@ -94,10 +94,19 @@ function(family_configure_example TARGET RTOS)
family_add_tinyusb(${TARGET} OPT_MCU_MCXA15)
endif()
+ # PORT is set per board (board.cmake), so pick the driver at configure time. Spelled out
+ # rather than $<IF:${PORT},...> so the port path stays greppable: test/hil/helper/hil_select.py
+ # maps a portable-driver change to the families whose build file names that directory.
+ if (PORT)
+ set(PORT_SRC ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c)
+ else ()
+ set(PORT_SRC ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c)
+ endif ()
+
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
- ${TOP}/src/portable/chipidea/$<IF:${PORT},ci_hs/dcd_ci_hs.c,ci_fs/dcd_ci_fs.c>
+ ${PORT_SRC}
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug b/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug
index fa7ab9e23..40f28baa9 100644
--- a/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug
+++ b/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug
@@ -21,7 +21,7 @@ void OnProjectLoad (void) {
Project.SetTracePortWidth (4);
// User settings
- File.Open ("../../../../../../examples/device/cdc_msc/cmake-build-pca10056/cdc_msc.elf");
+ File.Open ("../../../../../../examples/cmake-build-nrf52840dk/device/cdc_msc/cdc_msc.elf");
}
/*********************************************************************
diff --git a/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug b/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug
index 4ad0376a4..34b1841b0 100644
--- a/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug
+++ b/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug
@@ -29,9 +29,13 @@ void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
Project.SetTracePortWidth (4);
+ // +3 ns sample point: the DK's analog-switch/SWO stubs make TD=0 marginal
+ // (Ozone sends TraceSampleAdjust TD=0 when no timing is set); solid across
+ // the +2..+4 ns band with SB27/SB28 cut, SB57 (SWO) left intact
+ Project.SetTraceTiming (3000, 3000, 3000, 3000);
// User settings
- File.Open ("../../../../../../examples/device/cdc_msc/cmake-build-pca10095/cdc_msc.elf");
+ File.Open ("../../../../../../examples/cmake-build-nrf5340dk/device/cdc_msc/cdc_msc.elf");
}
/*********************************************************************
diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c
index 31a6bac9e..3cef4dac3 100644
--- a/hw/bsp/nrf/family.c
+++ b/hw/bsp/nrf/family.c
@@ -165,6 +165,12 @@ static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0);
//
//--------------------------------------------------------------------+
void board_init(void) {
+#if defined(TRACE_ETM) && defined(NRF5340_XXAA)
+ // SystemInit (ENABLE_TRACE) sets the TAD trace port to 64 MHz, which is
+ // marginal through the DK's switch stubs - 16 MHz streams reliably (matches the validated nrf52840dk) and is
+ // ample bandwidth for the 64 MHz core
+ NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_16MHz;
+#endif
#if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA)
// stop LF clock just in case we jump from application without reset
NRF_CLOCK->TASKS_LFCLKSTOP = 1UL;
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
diff --git a/hw/bsp/ra/boards/ra6m5_ek/ozone/ra6m5.jdebug b/hw/bsp/ra/boards/ra6m5_ek/ozone/ra6m5.jdebug
index ca18fed7c..466658f39 100644
--- a/hw/bsp/ra/boards/ra6m5_ek/ozone/ra6m5.jdebug
+++ b/hw/bsp/ra/boards/ra6m5_ek/ozone/ra6m5.jdebug
@@ -15,7 +15,7 @@ void OnProjectLoad (void) {
Project.SetDevice ("R7FA6M5BH");
Project.SetHostIF ("USB", "");
Project.SetTargetIF ("SWD");
- Project.SetTIFSpeed ("50 MHz");
+ Project.SetTIFSpeed ("4 MHz"); // 50 MHz SWD gave intermittent "Failed to initialize DAP"
Project.SetTraceSource ("Trace Pins");
Project.SetTracePortWidth (4);
diff --git a/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1.jdebug b/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1.jdebug
index 242a15db9..02d568240 100644
--- a/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1.jdebug
+++ b/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1.jdebug
@@ -10,10 +10,11 @@
*/
void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
Project.SetDevice ("R7FA8M1AH");
Project.SetHostIF ("USB", "");
Project.SetTargetIF ("SWD");
- Project.SetTIFSpeed ("50 MHz");
+ Project.SetTIFSpeed ("4 MHz"); // 50 MHz SWD gave intermittent "Failed to initialize DAP"
Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M85F.svd");
Project.AddSvdFile ("../../../../../../../cmsis-svd-data/data/Renesas/R7FA6M5BH.svd");
@@ -32,7 +33,7 @@ void OnProjectLoad (void) {
void BeforeTargetConnect (void) {
// Trace pin init is done by J-Link script file as J-Link script files are IDE independent
//Project.SetJLinkScript("../../../debug.jlinkscript");
- Project.SetJLinkScript ("$(ProjectDir)/Renesas_RA8_TracePins.pex");
+ Project.SetJLinkScript ("./ra8m1_trace.JLinkScript");
}
/*********************************************************************
@@ -40,12 +41,14 @@ void BeforeTargetConnect (void) {
* AfterTargetConnect
*
* Function description
-* Event handler routine. Optional.
+* Cache the boot-ROM range for the trace decoder on --attach sessions
+* too (the download hook that normally does this is skipped on attach).
*
**********************************************************************
*/
-//void AfterTargetConnect (void) {
-//}
+void AfterTargetConnect (void) {
+ Exec.Command("ReadIntoTraceCache 0x0 0x10000");
+}
/*********************************************************************
*
@@ -83,8 +86,12 @@ void BeforeTargetConnect (void) {
*/
void AfterTargetDownload (void) {
_SetupTarget();
+ // RA8 executes chip-ROM code at runtime (seen at ~0x3B20); without this the
+ // trace decoder dies there ("not covered by trace cache" -> unknown packet)
+ Exec.Command("ReadIntoTraceCache 0x0 0x10000");
}
+
/*********************************************************************
*
* BeforeTargetDisconnect
diff --git a/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1_trace.JLinkScript b/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1_trace.JLinkScript
new file mode 100644
index 000000000..3869c1eb7
--- /dev/null
+++ b/hw/bsp/ra/boards/ra8m1_ek/ozone/ra8m1_trace.JLinkScript
@@ -0,0 +1,20 @@
+/* RA8M1 pin trace: CSTF funnel and TMC are off the core ROM table (AP1) -
+ * declare them or trace init cannot route the M85 ETM stream (addresses per
+ * SEGGER's RA8 trace example script). Pins + TRCKCR belong to firmware
+ * (trace_etm_init): the SEGGER pex also muxed them at trace start, and its
+ * clock choice fought the firmware's mid-run = decoder desync.
+ */
+int ConfigTargetSettings(void) {
+ JLINK_ExecCommand("CORESIGHT_SetCSTFBaseAddr = 0x80013000 ForceUnlock = 1 APIndex = 1");
+ JLINK_ExecCommand("CORESIGHT_SetTMCBaseAddr = 0x80014000 ForceUnlock = 1 APIndex = 1");
+ return 0;
+}
+
+/* Replace J-Link's built-in RA8 trace start, which enables the trace clock
+ * from reset - bsp_clock_init's MOCO -> 480 MHz PLL switch would then step
+ * TRCLK mid-stream and desync the decoder. The firmware's trace_etm_init
+ * enables TRCKCR at the final clock instead.
+ */
+int OnTraceStart(void) {
+ return 0;
+}
diff --git a/hw/bsp/ra/boards/ra8m1_ek/ra_gen/bsp_clock_cfg.h b/hw/bsp/ra/boards/ra8m1_ek/ra_gen/bsp_clock_cfg.h
index f2f1ae0c9..25638f02b 100644
--- a/hw/bsp/ra/boards/ra8m1_ek/ra_gen/bsp_clock_cfg.h
+++ b/hw/bsp/ra/boards/ra8m1_ek/ra_gen/bsp_clock_cfg.h
@@ -51,6 +51,9 @@
#define BSP_CFG_CANFDCLK_DIV (BSP_CLOCKS_CANFD_CLOCK_DIV_8) /* CANFDCLK Div /8 */
#define BSP_CFG_I3CCLK_DIV (BSP_CLOCKS_I3C_CLOCK_DIV_3) /* I3CCLK Div /3 */
#define BSP_CFG_UCK_DIV (BSP_CLOCKS_USB_CLOCK_DIV_5) /* UCK Div /5 */
-#define BSP_CFG_U60CK_DIV (BSP_CLOCKS_USB_CLOCK_DIV_8) /* U60CK Div /8 */
+/* U60CK Div /8: PLL1P 480 MHz -> 60 MHz. Hand-fixed: Smart Configurator emitted the USB_ macro
+ * namespace (BSP_CLOCKS_USB_CLOCK_DIV_8 = 7, rejected by USB60CKDIVCR -> link clock ran at
+ * 480 MHz); configuration.xml already says u60ck.div.8, so keep the USB60_ macro if regenerating. */
+#define BSP_CFG_U60CK_DIV (BSP_CLOCKS_USB60_CLOCK_DIV_8)
#define BSP_CFG_OCTA_DIV (BSP_CLOCKS_OCTA_CLOCK_DIV_4) /* OCTASPICLK Div /4 */
#endif /* BSP_CLOCK_CFG_H_ */
diff --git a/hw/bsp/ra/family.c b/hw/bsp/ra/family.c
index c8a4d33d9..307644972 100644
--- a/hw/bsp/ra/family.c
+++ b/hw/bsp/ra/family.c
@@ -99,13 +99,32 @@ void board_init(void) {
R_IOPORT_Open(&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
#ifdef TRACE_ETM
- // TRCKCR is protected by PRCR bit0 register
- R_SYSTEM->PRCR = (uint16_t) (BSP_PRV_PRCR_KEY | 0x01);
+ // TRCKCR is only writable while a debugger is connected (RA HUM) - a
+ // standalone boot must skip trace init or the write wedges the chip into
+ // an un-attachable crash loop (recover: power-cycle + immediate erase)
+ if (DCB->DHCSR & DCB_DHCSR_C_DEBUGEN_Msk) {
+ // TRCKCR is protected by PRCR bit0 register
+ R_SYSTEM->PRCR = (uint16_t) (BSP_PRV_PRCR_KEY | 0x01);
- // Enable trace clock (max 100Mhz). Since PLL/CPU is 200Mhz, clock div = 2
- R_SYSTEM->TRCKCR = R_SYSTEM_TRCKCR_TRCKEN_Msk | 0x01;
+ // TCLK pin = TRCLK/2; set the divider with TRCKEN=0 first (HUM procedure).
+ // Values are the empirical per-board ceilings.
+#if defined(BSP_MCU_GROUP_RA8M1)
+ // 480 MHz CPU: /4 -> 120 MHz TRCLK, 60 MHz pin - chip max, clean on
+ // EK-RA8M1 with the committed empty-OnTraceStart JLinkScript (which
+ // defers the trace clock to firmware; without it the FSP MOCO->PLL
+ // switch steps the clock mid-stream and any divider fails)
+ R_SYSTEM->TRCKCR = 0x02;
+ R_SYSTEM->TRCKCR = R_SYSTEM_TRCKCR_TRCKEN_Msk | 0x02;
+#else
+ // RA6M5 200 MHz CPU: /4 -> 50 MHz TRCLK, 25 MHz pin. /2 (50 MHz pin) is
+ // silent on the EK-RA6M5 in every combination - board path ceiling,
+ // reconfirmed with J9 closed and the OnTraceStart override
+ R_SYSTEM->TRCKCR = 0x02;
+ R_SYSTEM->TRCKCR = R_SYSTEM_TRCKCR_TRCKEN_Msk | 0x02;
+#endif
- R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_KEY;
+ R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_KEY;
+ }
#endif
#if CFG_TUSB_OS == OPT_OS_FREERTOS
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
index 0a7dd4d23..08384b0cd 100644
--- a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
@@ -1,3 +1,17 @@
set(PICO_PLATFORM rp2350-arm-s)
set(PICO_BOARD pico2)
#set(OPENOCD_SERIAL E6614103E77C5A24)
+
+if (TRACE_ETM STREQUAL "1")
+ # TRACECLK is clk_sys/2 and must stay constant once trace is armed (a step
+ # desyncs the decoder), so the trace clock is pinned from crt0 onwards.
+ # 48 MHz (24 MHz TRACECLK) holds full-width trace on a typical fly-wire
+ # seating; a fresh, tight seating supports up to 72-80 MHz (re-qualify per
+ # the etm-trace skill), and >80 MHz needs a V3 probe + real trace board.
+ add_compile_definitions(
+ SYS_CLK_KHZ=48000
+ PLL_SYS_VCO_FREQ_HZ=1440000000
+ PLL_SYS_POSTDIV1=6
+ PLL_SYS_POSTDIV2=5
+ )
+endif ()
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug b/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug
new file mode 100644
index 000000000..ff48eb673
--- /dev/null
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* Pico 2 has no trace connector - fly-wire GPIO1-5 to the MIPI20:
+* TRACECLK=GPIO1->12, D0=GPIO2->14, D1=GPIO3->16, D2=GPIO4->18,
+* D3=GPIO5->20 (SEGGER validates this board the same way). Firmware must
+* be built with TRACE_ETM=1: it pins clk_sys to 48 MHz (board.cmake) so
+* the 4-bit port never saturates and the clock never steps mid-stream,
+* and keeps the us-timer free of TIMER DBGPAUSE (family.c). The whole
+* chip-side trace path (ETM/funnel/TPIU/pin mux) is armed by J-Link's
+* built-in RP2350 script at every resume - do NOT set a custom
+* JLinkScript here: it would replace that script and J-Link then fails
+* with "Required trace components for pin trace not found".
+* GPIO1 is the default UART0 RX: console TX still works, RX is lost.
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 48000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M33F.svd");
+
+ Project.SetDevice ("RP2350_M33_0");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("25 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-raspberry_pi_pico2/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ // intentionally empty: the RP2350 bootrom must run to validate the
+ // IMAGE_DEF and hand over to the app - setting SP/PC from the vector
+ // table bypasses it and the pico-sdk runtime never comes up
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ // intentionally empty: the RP2350 bootrom must run to validate the
+ // IMAGE_DEF and hand over to the app - setting SP/PC from the vector
+ // table bypasses it and the pico-sdk runtime never comes up
+}
diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c
index 55feec159..e12f51b14 100644
--- a/hw/bsp/rp2040/family.c
+++ b/hw/bsp/rp2040/family.c
@@ -153,7 +153,7 @@ static stdio_driver_t stdio_rtt = {
.in_chars = stdio_rtt_read
};
-void stdio_rtt_init(void) {
+static void stdio_rtt_init(void) {
stdio_set_driver_enabled(&stdio_rtt, true);
}
#endif
@@ -161,11 +161,28 @@ void stdio_rtt_init(void) {
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
+#if defined(TRACE_ETM) && defined(PICO_RP2350) && PICO_RP2350 == 1
+// J-Link's built-in RP2350 device script re-arms the whole chip-side trace
+// path (ETM/funnel/TPIU/pins) via OnTraceStart at every resume, so firmware
+// must NOT touch it - it only keeps the us-timer running while cores sit
+// debug-halted (default TIMER DBGPAUSE freezes it, and sleep_ms() then spins
+// forever after any debugger session).
+static void trace_etm_init(void) {
+ *(volatile uint32_t*) 0x400B002Cu = 0; // TIMER0 DBGPAUSE
+ *(volatile uint32_t*) 0x400B802Cu = 0; // TIMER1 DBGPAUSE
+}
+#else
+ #define trace_etm_init()
+#endif
+
void board_init(void)
{
#if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB)
// Set the system clock to a multiple of 12mhz for bit-banging USB with pico-usb
#if defined(PICO_RP2350) && PICO_RP2350 == 1
+ #ifdef TRACE_ETM
+ #error "TRACE_ETM pins clk_sys to 48 MHz (board.cmake) - too slow for PIO-USB, and a runtime clock switch desyncs the trace stream"
+ #endif
set_sys_clock_khz(156000, true); // rp2350 default is 150Mhz
#else
set_sys_clock_khz(120000, true); // rp2040 default is 125Mhz
@@ -199,10 +216,18 @@ void board_init(void)
#endif
#ifdef UART_DEV
- bi_decl(bi_2pins_with_func(UART_TX_PIN, UART_RX_PIN, GPIO_FUNC_UART));
uart_inst = uart_get_instance(UART_DEV);
+#if defined(TRACE_ETM) && defined(PICO_RP2350) && PICO_RP2350 == 1
+ // GPIO1 (default UART RX) is TRACECLK: TX-only console, and never touch
+ // GPIO1 - even a brief re-mux gaps the trace clock and desyncs the probe
+ bi_decl(bi_1pin_with_name(UART_TX_PIN, "UART TX"));
+ stdio_uart_init_full(uart_inst, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, -1);
+#else
+ bi_decl(bi_2pins_with_func(UART_TX_PIN, UART_RX_PIN, GPIO_FUNC_UART));
stdio_uart_init_full(uart_inst, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, UART_RX_PIN);
#endif
+#endif
+ trace_etm_init();
#if defined(LOGGER_RTT)
stdio_rtt_init();
diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake
index aab9a4fae..43b1dc234 100644
--- a/hw/bsp/rp2040/family.cmake
+++ b/hw/bsp/rp2040/family.cmake
@@ -28,6 +28,8 @@ elseif (PICO_PLATFORM STREQUAL "rp2350-arm-s" OR PICO_PLATFORM STREQUAL "rp2350"
set(OPENOCD_TARGET rp2350)
elseif (PICO_PLATFORM STREQUAL "rp2350-riscv")
set(JLINK_DEVICE rp2350_riscv_0)
+ # rp2350-riscv.cfg needs the raspberrypi/openocd fork: mainline's riscv
+ # target does not take the -dap/-ap-num the config uses
set(OPENOCD_TARGET rp2350-riscv)
endif()
diff --git a/hw/bsp/samd5x_e5x/boards/same54_xplained/ozone/same54.jdebug b/hw/bsp/samd5x_e5x/boards/same54_xplained/ozone/same54.jdebug
new file mode 100644
index 000000000..a0f8d5c3d
--- /dev/null
+++ b/hw/bsp/samd5x_e5x/boards/same54_xplained/ozone/same54.jdebug
@@ -0,0 +1,89 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* SAM E54 Xplained Pro carries a populated 20-pin Cortex Debug+ETM
+* connector (Table 5-11): TRACECLK=PC27, D0=PC28, D1=PC26, D2=PC25,
+* D3=PC24 - no rework needed. Firmware must be built with TRACE_ETM=1
+* (mux function H on those pins in board_init); TPIU/ETM are
+* ROM-table-discoverable so no J-Link script is required.
+* Trace clock is CPU/2 = 60 MHz at the stock 120 MHz core.
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 120000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd");
+
+ Project.SetDevice ("ATSAME54P20");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-same54_xplained/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c
index 71ef2d6ce..a2c3b70de 100644
--- a/hw/bsp/samd5x_e5x/family.c
+++ b/hw/bsp/samd5x_e5x/family.c
@@ -87,6 +87,31 @@ void USB_3_Handler(void) { USB_Any_Handler(); }
static void max3421_init(void);
#endif
+#if defined(TRACE_ETM)
+// same54_xplained routes 4-bit trace to its 20-pin Cortex Debug+ETM header:
+// TRACECLK=PC27, D0=PC28, D1=PC26, D2=PC25, D3=PC24 - all peripheral
+// function H (CM4 trace). TPIU/ETM are ROM-table-discoverable; the debugger
+// arms them, firmware only muxes the pins.
+static void trace_etm_init(void) {
+ // the CM4 trace unit runs from its own GCLK channel (47): feed it GCLK0
+ // (CPU clock) - without this the pins mux fine but the port stays silent
+ GCLK->PCHCTRL[47].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
+ while (!(GCLK->PCHCTRL[47].reg & GCLK_PCHCTRL_CHEN)) {}
+
+ const uint8_t pin[] = {24, 25, 26, 27, 28};
+ for (unsigned i = 0; i < 5; i++) {
+ PORT->Group[2].PINCFG[pin[i]].reg = PORT_PINCFG_PMUXEN | PORT_PINCFG_DRVSTR;
+ if (pin[i] & 1) {
+ PORT->Group[2].PMUX[pin[i] >> 1].bit.PMUXO = 7; // function H
+ } else {
+ PORT->Group[2].PMUX[pin[i] >> 1].bit.PMUXE = 7;
+ }
+ }
+}
+#else
+ #define trace_etm_init()
+#endif
+
void board_init(void) {
// Clock init ( follow hpl_init.c )
hri_nvmctrl_set_CTRLA_RWS_bf(NVMCTRL, 0);
@@ -104,6 +129,8 @@ void board_init(void) {
// Init 1ms tick timer (samd SystemCoreClock may not correct)
SystemCoreClock = CONF_CPU_FREQUENCY;
+ trace_etm_init();
+
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
diff --git a/hw/bsp/same7x/boards/same70_xplained/board.h b/hw/bsp/same7x/boards/same70_xplained/board.h
index 85e23deb8..86edf606f 100644
--- a/hw/bsp/same7x/boards/same70_xplained/board.h
+++ b/hw/bsp/same7x/boards/same70_xplained/board.h
@@ -52,6 +52,10 @@ extern "C" {
#define UART_PORT_CLOCK ID_USART1
#define BOARD_USART USART1
+// TRACE_ETM: this board wires the KSZ8081 PHY reset to PC10; the family
+// trace init holds it in reset (RMII rx lines share the trace pads)
+#define TRACE_ETM_QUIET_ENET_PHY 1
+
static inline void board_vbus_set(uint8_t rhport, bool state) {
(void) rhport;
(void) state;
diff --git a/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug b/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug
new file mode 100644
index 000000000..f024f0ceb
--- /dev/null
+++ b/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug
@@ -0,0 +1,115 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* SAM E70 Xplained: solder a 20-pin 50-mil header on the J403 ETM footprint
+* (bottom side). TRACECLK=PD8 (peripheral D), TRACED0-3=PD4-7 (peripheral C),
+* shared with the Ethernet PHY - no Ethernet while tracing. TRACE_ETM=1
+* builds mux the pins and clock the TPIU from PCK3=MCK; TPIU/ETM are
+* ROM-table-discoverable so no J-Link script is required.
+* Trace clock pin is PCK3/2 = 75 MHz at the stock 300 MHz core (MCK 150).
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 300000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M7F.svd");
+
+ Project.SetDevice ("ATSAME70Q21B");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-same70_xplained/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+
+ // TPIU trace clock = PCK3; it must run BEFORE Ozone arms the trace
+ // components (TPIU programming while PCK3 is stopped is lost and the port
+ // emits unformatted garbage). A target reset wipes the PMC, so this runs
+ // in the post-reset/post-download hooks, not AfterTargetConnect.
+ Target.WriteU32 (0x400E064C, 0x00000014); // PMC_PCK3: CSS=MCK, PRESS=/2
+ Target.WriteU32 (0x400E0600, 0x00000800); // PMC_SCER: PCK3 on
+ // wait for PCKRDY3 (bounded) before Ozone arms the trace components
+ int i;
+ i = 0;
+ while (((Target.ReadU32 (0x400E0668) & 0x00000800) == 0) && (i < 100)) {
+ i = i + 1;
+ }
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+
+ // TPIU trace clock = PCK3; it must run BEFORE Ozone arms the trace
+ // components (TPIU programming while PCK3 is stopped is lost and the port
+ // emits unformatted garbage). A target reset wipes the PMC, so this runs
+ // in the post-reset/post-download hooks, not AfterTargetConnect.
+ Target.WriteU32 (0x400E064C, 0x00000014); // PMC_PCK3: CSS=MCK, PRESS=/2
+ Target.WriteU32 (0x400E0600, 0x00000800); // PMC_SCER: PCK3 on
+ // wait for PCKRDY3 (bounded) before Ozone arms the trace components
+ int i;
+ i = 0;
+ while (((Target.ReadU32 (0x400E0668) & 0x00000800) == 0) && (i < 100)) {
+ i = i + 1;
+ }
+}
diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c
index d02e6c5f1..8ec6a708b 100644
--- a/hw/bsp/same7x/family.c
+++ b/hw/bsp/same7x/family.c
@@ -62,6 +62,38 @@ void board_init(void) {
/* Disable Watchdog */
hri_wdt_set_MR_WDDIS_bit(WDT);
+#if defined(TRACE_ETM)
+ // same70_xplained J403 (Cortex Debug+ETM footprint, bottom side) carries
+ // 4-bit trace: TRACECLK=PD8 (peripheral D), TRACED0-3=PD4-7 (peripheral C).
+#ifdef TRACE_ETM_QUIET_ENET_PHY
+ // The trace pins double as the Ethernet PHY's RMII receive lines
+ // (PD4=CRS_DV, PD5/6=RXD0/1, PD7=RXER - PHY OUTPUTS): hold the KSZ8081 in
+ // reset or it drives against the trace stream. The reset net is a BOARD
+ // property (same70_xplained: PHY_RESET=PC10), hence the board.h gate.
+ _pmc_enable_periph_clock(ID_PIOC);
+ gpio_set_pin_level(GPIO(GPIO_PORTC, 10), false);
+ gpio_set_pin_direction(GPIO(GPIO_PORTC, 10), GPIO_DIRECTION_OUT);
+ gpio_set_pin_function(GPIO(GPIO_PORTC, 10), GPIO_PIN_FUNCTION_OFF);
+#endif
+
+ // The TPIU is clocked from PCK3 (datasheet 16.7.4) - run it from MCK.
+ // skip if the debugger already started PCK3 (reprogramming glitches the
+ // clock mid-stream and desyncs the decoder)
+ uint32_t const pck3 = PMC_PCK_CSS_MCK | PMC_PCK_PRES(1); // MCK/2 = 75 MHz -> 37.5 MHz pin
+ if (PMC->PMC_PCK[3] != pck3 || !(PMC->PMC_SR & PMC_SR_PCKRDY3)) {
+ PMC->PMC_PCK[3] = pck3;
+ PMC->PMC_SCER = PMC_SCER_PCK3;
+ while (!(PMC->PMC_SR & PMC_SR_PCKRDY3)) {}
+ }
+ _pmc_enable_periph_clock(ID_PIOD);
+ uint32_t const clk_pin = PIO_PD8D_TPIU_TRACECLK;
+ uint32_t const dat_pin = PIO_PD4C_TPIU_TRACED0 | PIO_PD5C_TPIU_TRACED1 |
+ PIO_PD6C_TPIU_TRACED2 | PIO_PD7C_TPIU_TRACED3;
+ PIOD->PIO_ABCDSR[0] = (PIOD->PIO_ABCDSR[0] | clk_pin) & ~dat_pin; // D=11, C=01
+ PIOD->PIO_ABCDSR[1] |= clk_pin | dat_pin;
+ PIOD->PIO_PDR = clk_pin | dat_pin; // hand the pins to the peripheral
+#endif
+
#ifdef LED_PIN
_pmc_enable_periph_clock(LED_PORT_CLOCK);
gpio_set_pin_level(LED_PIN, LED_STATE_OFF);
diff --git a/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h b/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
index 18c13017a..959dc4828 100644
--- a/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
+++ b/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
@@ -88,7 +88,12 @@ static inline void SystemClock_Config(void) {
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
+ #ifdef TRACE_ETM
+ RCC_OscInitStruct.PLL.PLLN = 100; // 100 MHz core: the Nucleo trace path (CN5 via solder bridges)
+ // corrupts the trace stream at higher TRACECLK (= SYSCLK/2)
+ #else
RCC_OscInitStruct.PLL.PLLN = 250;
+ #endif
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
diff --git a/hw/bsp/stm32h5/boards/stm32h563nucleo/ozone/stm32h563.jdebug b/hw/bsp/stm32h5/boards/stm32h563nucleo/ozone/stm32h563.jdebug
new file mode 100644
index 000000000..04f4e4582
--- /dev/null
+++ b/hw/bsp/stm32h5/boards/stm32h563nucleo/ozone/stm32h563.jdebug
@@ -0,0 +1,113 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* Nucleo-H563ZI trace: PE2-PE6 reach the MIPI-20 connector (CN5) only
+* with SB8, SB9, SB64, SB68, SB70, SB71, SB78 removed (MB1404 UM).
+* Firmware must be built with TRACE_ETM=1 (trace pin + DBGMCU init).
+*
+* The trace path through the solder bridges is signal-marginal: reliable
+* only at 100 MHz core (TRACE_ETM builds select this automatically in
+* board.h), port width 1 and +5 ns sample timing (validated empirically;
+* width 4 or 250 MHz core corrupts the stream within ~100 ms).
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (1);
+ Project.SetTraceTiming (5000, 5000, 5000, 5000);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 100000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M33F.svd");
+
+ Project.SetDevice ("STM32H563ZI");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-stm32h563nucleo/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetConnect
+*
+* Function description
+* Enable the trace clock domain (DBGMCU_CR: TRACE_IOEN | TRACE_CLKEN |
+* TRACE_MODE=4-bit) BEFORE Ozone touches the trace CoreSight components.
+* On STM32H5 an access to unclocked trace components hangs the debug AP
+* ("Failed to read target status") until the board is power-cycled.
+*
+**********************************************************************
+*/
+void AfterTargetConnect (void) {
+ unsigned int cr;
+ cr = Target.ReadU32(0x44024004); // DBGMCU_CR
+ // clock the domain (CLKEN|MODE=4-bit) but keep the pins OFF (clear IOEN):
+ // the pins must only go live via firmware trace_etm_init() AFTER the system
+ // clock switch, or the mid-trace frequency change desyncs the decoder.
+ Target.WriteU32(0x44024004, (cr & 0xFFFFFFEF) | 0xE0);
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
diff --git a/hw/bsp/stm32h5/family.c b/hw/bsp/stm32h5/family.c
index 867171734..36a95ac8c 100644
--- a/hw/bsp/stm32h5/family.c
+++ b/hw/bsp/stm32h5/family.c
@@ -99,6 +99,24 @@ static UART_HandleTypeDef UartHandle = {
};
#endif
+#ifdef TRACE_ETM
+static void trace_etm_init(void) {
+ // H5 trace pins are PE2 to PE6 (Nucleo-144: requires trace solder-bridge config, see board docs)
+ GPIO_InitTypeDef gpio_init;
+ gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
+ gpio_init.Mode = GPIO_MODE_AF_PP;
+ gpio_init.Pull = GPIO_PULLUP;
+ gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ gpio_init.Alternate = GPIO_AF0_TRACE;
+ HAL_GPIO_Init(GPIOE, &gpio_init);
+
+ // Enable trace port + clock, synchronous 4-bit mode
+ DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_CLKEN | DBGMCU_CR_TRACE_MODE;
+}
+#else
+#define trace_etm_init()
+#endif
+
void board_init(void) {
// Cache UID before ICACHE is enabled (STM32H5 errata: reading UID_BASE with ICACHE causes hard fault)
volatile uint32_t* stm32_uuid = (volatile uint32_t*) UID_BASE;
@@ -127,6 +145,8 @@ void board_init(void) {
__HAL_RCC_GPIOI_CLK_ENABLE();
#endif
+ trace_etm_init();
+
#if CFG_TUSB_OS == OPT_OS_NONE
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
diff --git a/hw/bsp/stm32h5/linker/stm32h533xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h533xx_flash.icf
new file mode 100644
index 000000000..dc97788ae
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h533xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x20043FFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/ozone/stm32h743.jdebug b/hw/bsp/stm32h7/boards/stm32h743eval/ozone/stm32h743.jdebug
index 32a8155c1..f9780147d 100644
--- a/hw/bsp/stm32h7/boards/stm32h743eval/ozone/stm32h743.jdebug
+++ b/hw/bsp/stm32h7/boards/stm32h743eval/ozone/stm32h743.jdebug
@@ -10,6 +10,7 @@
*/
void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
Project.SetTraceTiming (100, 100, 100, 100);
Project.SetSWO (0);
Edit.SysVar (VAR_TRACE_CORE_CLOCK, 200000000);
@@ -22,7 +23,7 @@ void OnProjectLoad (void) {
Project.SetTargetIF ("SWD");
Project.SetTIFSpeed ("50 MHz");
- File.Open ("../../../../../../examples/device/cdc_msc/cmake-build-stm32h743eval/cdc_msc.elf");
+ File.Open ("../../../../../../examples/cmake-build-stm32h743eval/device/cdc_msc/cdc_msc.elf");
// File.Open ("../../../../../../examples/cmake-build-stm32h743eval_host1/host/cdc_msc_hid/cdc_msc_hid.elf");
}
diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h
index 996eb1515..098fc0bed 100644
--- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h
+++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h
@@ -123,7 +123,13 @@ static inline void SystemClock_Config(void)
RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL1.PLLM = 12;
+#ifdef TRACE_ETM
+ // 300 MHz core -> 50 MHz trace clock: at 600 MHz the stream survives idle
+ // but dies (unknown trace packet) during IRQ-heavy bursts, e.g. USB traffic
+ RCC_OscInitStruct.PLL1.PLLN = 150;
+#else
RCC_OscInitStruct.PLL1.PLLN = 300;
+#endif
RCC_OscInitStruct.PLL1.PLLP = 1;
RCC_OscInitStruct.PLL1.PLLQ = 2;
RCC_OscInitStruct.PLL1.PLLR = 2;
diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3.jdebug b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3.jdebug
new file mode 100644
index 000000000..f6658d2d7
--- /dev/null
+++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3.jdebug
@@ -0,0 +1,94 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* Nucleo-H7S3L8 wires 4-bit trace to the CN1 MIPI20 natively (no rework):
+* TRACE_CLK/D0 = PE2/PE3, TRACE_D1/D2/D3 = PG14/PD2/PC12 (MB1737 Table 7).
+* Firmware must be built with TRACE_ETM=1 (trace pin mux + DBGMCU
+* DBGCKEN/TRACECLKEN in board_init).
+*
+* TRACE_ETM builds run a 300 MHz core (board.h) -> 50 MHz trace clock
+* (cpu/3/2). Width 2 on the stub-free D0/D1 lines: SB11/SB12 (default ON)
+* stub D2/D3 onto Zio CN8 and the 4-bit stream dies under IRQ-heavy USB
+* traffic (idle is clean) - remove SB11/SB12 to try width 4 / 600 MHz.
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ // declares the off-ROM-table CSTF/TMC/TPIU (see the script header)
+ Project.SetJLinkScript ("./stm32h7s3_trace.JLinkScript");
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (2);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 300000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M7F.svd");
+
+ Project.SetDevice ("STM32H7S3L8");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-stm32h7s3nucleo/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3_trace.JLinkScript b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3_trace.JLinkScript
new file mode 100644
index 000000000..5ef4f164d
--- /dev/null
+++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/ozone/stm32h7s3_trace.JLinkScript
@@ -0,0 +1,11 @@
+/* STM32H7RS pin trace: the CSTF funnel, TMC (ETF) and TPIU are not in the
+ * core ROM table - declare them or J-Link aborts trace init with "Required
+ * trace components for pin trace not found!" (addresses per SEGGER's
+ * NUCLEO-H7S3L8 trace example script; AP0).
+ */
+int ConfigTargetSettings(void) {
+ JLINK_ExecCommand("CORESIGHT_SetCSTFBaseAddr = 0x5C013000 ForceUnlock = 1 APIndex = 0");
+ JLINK_ExecCommand("CORESIGHT_SetTMCBaseAddr = 0x5C014000 ForceUnlock = 1 APIndex = 0");
+ JLINK_ExecCommand("CORESIGHT_SetTPIUBaseAddr = 0x5C015000 ForceUnlock = 1 APIndex = 0");
+ return 0;
+}
diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c
index b0841c947..385b3c929 100644
--- a/hw/bsp/stm32h7rs/family.c
+++ b/hw/bsp/stm32h7rs/family.c
@@ -98,17 +98,24 @@ void OTG_HS_IRQHandler(void) {
#ifdef TRACE_ETM
void trace_etm_init(void) {
- // H7 trace pin is PE2 to PE6
- GPIO_InitTypeDef gpio_init;
- gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
+ // Nucleo-H7S3L8 routes 4-bit trace to the CN1 MIPI20: TRACE_CLK/D0 on
+ // PE2/PE3, TRACE_D1/D2/D3 on the PG14/PD2/PC12 alternates (MB1737 Table 7).
+ // No pull: pull-ups degrade the edges at the 100 MHz trace clock (= cpu/3/2)
+ GPIO_InitTypeDef gpio_init;
gpio_init.Mode = GPIO_MODE_AF_PP;
- gpio_init.Pull = GPIO_PULLUP;
+ gpio_init.Pull = GPIO_NOPULL;
gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
gpio_init.Alternate = GPIO_AF0_TRACE;
+ gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3;
HAL_GPIO_Init(GPIOE, &gpio_init);
+ gpio_init.Pin = GPIO_PIN_14;
+ HAL_GPIO_Init(GPIOG, &gpio_init);
+ gpio_init.Pin = GPIO_PIN_2;
+ HAL_GPIO_Init(GPIOD, &gpio_init);
+ gpio_init.Pin = GPIO_PIN_12;
+ HAL_GPIO_Init(GPIOC, &gpio_init);
- // Enable trace clk, also in D1 and D3 domain
- DBGMCU->CR |= DBGMCU_CR_DBG_TRACECKEN | DBGMCU_CR_DBG_CKD1EN | DBGMCU_CR_DBG_CKD3EN;
+ DBGMCU->CR |= DBGMCU_CR_DBGCKEN | DBGMCU_CR_TRACECLKEN;
}
#else
#define trace_etm_init()
diff --git a/hw/bsp/stm32l4/boards/stm32l412nucleo/board.h b/hw/bsp/stm32l4/boards/stm32l412nucleo/board.h
index a5250eda9..7f63ec431 100644
--- a/hw/bsp/stm32l4/boards/stm32l412nucleo/board.h
+++ b/hw/bsp/stm32l4/boards/stm32l412nucleo/board.h
@@ -64,9 +64,10 @@
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 1
- * MSI Frequency(Hz) = 8000000
- * PLL_M = 1
- * PLL_N = 10
+ * MSI Frequency(Hz) = 48000000
+ * LSE Frequency(Hz) = 32768
+ * PLL_M = 6
+ * PLL_N = 20
* PLL_Q = 2
* PLL_R = 2
* VDD(V) = 3.3
@@ -78,29 +79,35 @@ static inline void board_clock_init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_CRSInitTypeDef RCC_CRSInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
+ /* HAL clock setup reconfigures its tick while MSI is the reset SYSCLK. */
+ HAL_InitTick((1UL << __NVIC_PRIO_BITS) - 1UL);
+
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
- RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI;
+ RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+ RCC_OscInitStruct.MSIState = RCC_MSI_ON;
+ RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
+ RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLM = 1;
- RCC_OscInitStruct.PLL.PLLN = 10;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
+ RCC_OscInitStruct.PLL.PLLM = 6;
+ RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
+ /* Stabilize MSI against the on-board 32.768 kHz LSE crystal. */
+ HAL_RCCEx_EnableMSIPLLMode();
+
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
@@ -112,24 +119,9 @@ static inline void board_clock_init(void)
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
- /** Enable the SYSCFG APB clock
- */
- __HAL_RCC_CRS_CLK_ENABLE();
-
- /** Configures CRS
- */
- RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
- RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
- RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
- RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000);
- RCC_CRSInitStruct.ErrorLimitValue = 34;
- RCC_CRSInitStruct.HSI48CalibrationValue = 32;
-
- HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);
-
- /* Select HSI48 output as USB clock source */
+ /* Use the same LSE-trimmed MSI source for USB and the CPU PLL. */
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
- PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
+ PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/* Select PLL output as UART clock source */
diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h
index be9ea7a31..873c004d9 100644
--- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h
+++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h
@@ -152,7 +152,13 @@ static void SystemClock_Config(void) {
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK4 | RCC_CLOCKTYPE_PCLK5);
RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_IC1;
RCC_ClkInitStruct.IC1Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1;
+#ifdef TRACE_ETM
+ // 300 MHz CPU -> 37.5 MHz TPIU clock (fixed cpu/8): at 600 MHz the trace
+ // stream dies with unknown-packet decode errors in the startup burst
+ RCC_ClkInitStruct.IC1Selection.ClockDivider = 4;
+#else
RCC_ClkInitStruct.IC1Selection.ClockDivider = 2;
+#endif
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_IC2_IC6_IC11;
RCC_ClkInitStruct.IC2Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1;
RCC_ClkInitStruct.IC2Selection.ClockDivider = 3;
diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/ozone/stm32n657.jdebug b/hw/bsp/stm32n6/boards/stm32n657nucleo/ozone/stm32n657.jdebug
new file mode 100644
index 000000000..16eead280
--- /dev/null
+++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/ozone/stm32n657.jdebug
@@ -0,0 +1,94 @@
+/*********************************************************************
+*
+* OnProjectLoad
+*
+* Function description
+* Project load routine. Required.
+*
+* Notes
+* Nucleo-N657X0-Q wires 4-bit trace to the CN1 MIPI20 natively (SB36/38/
+* 39/40/41 fitted by default): TRACE_CLK = PB3, D0/D1/D2/D3 =
+* PE3/PB0/PB6/PB7 (MB1940 Table 5). No J-Link script needed - the N6
+* trace components sit behind a ROM table J-Link discovers natively.
+*
+* BOOT1 (JP2) must select Development boot (BOOT1 = 1): the N657 is
+* flashless, the app is a RAM image (AXISRAM2) loaded by the debugger,
+* and in flash boot the bootROM parks the chip un-attachable.
+* Firmware must be built with TRACE_ETM=1 (pin mux + DBGMCU
+* DBGCLKEN/TRACECLKEN). Trace clock = cpu/8. TRACE_ETM builds run a 300 MHz core (board.h) ->
+* 37.5 MHz TPIU clock: 600 MHz kills the stream in the startup burst.
+*
+**********************************************************************
+*/
+void OnProjectLoad (void) {
+ Project.SetTraceSource ("Trace Pins");
+ Project.SetTracePortWidth (4);
+ Project.SetSWO (0);
+ Edit.SysVar (VAR_TRACE_CORE_CLOCK, 300000000);
+ Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M55F.svd");
+
+ Project.SetDevice ("STM32N657X0");
+ Project.SetHostIF ("USB", "");
+ Project.SetTargetIF ("SWD");
+ Project.SetTIFSpeed ("4 MHz");
+
+ File.Open ("../../../../../../examples/cmake-build-stm32n657nucleo/device/cdc_msc/cdc_msc.elf");
+}
+
+/*********************************************************************
+*
+* AfterTargetReset
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetReset (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
+
+/*********************************************************************
+*
+* AfterTargetDownload
+*
+* Function description
+* Event handler routine.
+* - Sets the PC register to program reset value.
+* - Sets the SP register to program reset value on Cortex-M.
+*
+**********************************************************************
+*/
+void AfterTargetDownload (void) {
+ unsigned int SP;
+ unsigned int PC;
+ unsigned int VectorTableAddr;
+
+ VectorTableAddr = Elf.GetBaseAddr();
+
+ if (VectorTableAddr == 0xFFFFFFFF) {
+ Util.Log("Project file error: failed to get program base");
+ } else {
+ SP = Target.ReadU32(VectorTableAddr);
+ Target.SetReg("SP", SP);
+
+ PC = Target.ReadU32(VectorTableAddr + 4);
+ Target.SetReg("PC", PC);
+ }
+}
diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c
index 80de20c6a..9d3faa1f2 100644
--- a/hw/bsp/stm32n6/family.c
+++ b/hw/bsp/stm32n6/family.c
@@ -110,6 +110,27 @@ void USB1_OTG_HS_IRQHandler(void) {
tusb_int_handler(0, true);
}
+#ifdef TRACE_ETM
+static void trace_etm_init(void) {
+ // Nucleo-N657X0-Q routes 4-bit trace to the CN1 MIPI20 natively:
+ // TRACE_CLK = PB3, D0 = PE3, D1 = PB0, D2 = PB6, D3 = PB7 (MB1940 Table 5)
+ GPIO_InitTypeDef gpio_init;
+ gpio_init.Mode = GPIO_MODE_AF_PP;
+ gpio_init.Pull = GPIO_NOPULL;
+ gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ gpio_init.Alternate = GPIO_AF0_TRACE;
+ gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
+ HAL_GPIO_Init(GPIOB, &gpio_init);
+ gpio_init.Pin = GPIO_PIN_3;
+ HAL_GPIO_Init(GPIOE, &gpio_init);
+
+ // trace clock (ck_cpu_tpiu) is a fixed cpu/8 - just enable it
+ DBGMCU->CR |= DBGMCU_CR_DBGCLKEN | DBGMCU_CR_TRACECLKEN;
+}
+#else
+ #define trace_etm_init()
+#endif
+
void board_init(void) {
/* Enable BusFault and SecureFault handlers (HardFault is default) */
SCB->SHCSR |= (SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_SECUREFAULTENA_Msk);
@@ -148,6 +169,7 @@ void board_init(void) {
for (uint8_t i = 0; i < TU_ARRAY_SIZE(board_pindef); i++) {
HAL_GPIO_Init(board_pindef[i].port, &board_pindef[i].pin_init);
}
+ trace_etm_init();
NVIC_SetPriority(UCPD1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
NVIC_EnableIRQ(UCPD1_IRQn);