diff options
| author | hathach <[email protected]> | 2026-07-09 23:38:48 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-09 23:38:48 +0700 |
| commit | 90d48c2a632751c1b38831655e256f1bc1918a47 (patch) | |
| tree | 5be772503ae8011e9b5bbc0183a4aebf29bfeb1b | |
| parent | c97c0a12bc5ab8e79aa3db0a777e0219692b5751 (diff) | |
bsp(ch32): naked fsdev ISRs so nested USBD IRQs return safely
The three USBD lines nest under QingKe HWSTK; gcc's interrupt prologue
corrupts the return, so rely on the hardware stack and bare mret.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
| -rw-r--r-- | hw/bsp/ch32v20x/family.c | 38 | ||||
| -rw-r--r-- | hw/bsp/ch32v30x/family.c | 9 |
2 files changed, 28 insertions, 19 deletions
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/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; |
