From def93400929fa745ec5f88db87362ddcc4e5630b Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 10 Aug 2026 15:55:05 +0800 Subject: [PATCH 01/17] fix(halv2): adapt UART reset and IRQ helpers --- libraries/SrcWrapper/src/stm32/uart.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libraries/SrcWrapper/src/stm32/uart.c b/libraries/SrcWrapper/src/stm32/uart.c index 62ae6bd200..d5558f12b9 100644 --- a/libraries/SrcWrapper/src/stm32/uart.c +++ b/libraries/SrcWrapper/src/stm32/uart.c @@ -692,9 +692,14 @@ void uart_deinit(serial_t *obj) #endif #if defined(USART6_BASE) case UART6_INDEX: +#if defined(USE_HALV2_DRIVER) + HAL_RCC_USART6_Reset(); + HAL_RCC_USART6_DisableClock(); +#else __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); __HAL_RCC_USART6_CLK_DISABLE(); +#endif break; #endif #if defined(LPUART1_BASE) @@ -725,9 +730,14 @@ void uart_deinit(serial_t *obj) #endif #if defined(UART7_BASE) case UART7_INDEX: +#if defined(USE_HALV2_DRIVER) + HAL_RCC_UART7_Reset(); + HAL_RCC_UART7_DisableClock(); +#else __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); __HAL_RCC_UART7_CLK_DISABLE(); +#endif break; #elif defined(USART7_BASE) case UART7_INDEX: @@ -1460,7 +1470,11 @@ void UART5_IRQHandler(void) #if defined(USART6_BASE) && !defined(STM32F0xx) && !defined(STM32G0xx) void USART6_IRQHandler(void) { +#if defined(USE_HALV2_DRIVER) + HAL_CORTEX_NVIC_ClearPendingIRQ(USART6_IRQn); +#else HAL_NVIC_ClearPendingIRQ(USART6_IRQn); +#endif HAL_UART_IRQHandler(uart_handlers[UART6_INDEX]); } #endif @@ -1490,7 +1504,11 @@ void LPUART1_IRQHandler(void) #if defined(UART7_BASE) void UART7_IRQHandler(void) { +#if defined(USE_HALV2_DRIVER) + HAL_CORTEX_NVIC_ClearPendingIRQ(UART7_IRQn); +#else HAL_NVIC_ClearPendingIRQ(UART7_IRQn); +#endif HAL_UART_IRQHandler(uart_handlers[UART7_INDEX]); } #endif From dc3313b745960385b8f8dbdf2c303dca6ac247e8 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 10 Aug 2026 15:55:25 +0800 Subject: [PATCH 02/17] feat(usb): add C5 HAL v2 CDC support --- libraries/USBDevice/inc/usbd_conf.h | 12 +- libraries/USBDevice/src/cdc/usbd_cdc.c | 12 +- libraries/USBDevice/src/usbd_conf.c | 5 +- libraries/USBDevice/src/usbd_conf_c5.c | 251 +++++++++++++++++++++++++ libraries/USBDevice/src/usbd_if.c | 7 + 5 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 libraries/USBDevice/src/usbd_conf_c5.c diff --git a/libraries/USBDevice/inc/usbd_conf.h b/libraries/USBDevice/inc/usbd_conf.h index a08fa61e7e..1f19cd33ec 100644 --- a/libraries/USBDevice/inc/usbd_conf.h +++ b/libraries/USBDevice/inc/usbd_conf.h @@ -30,7 +30,17 @@ extern "C" { #include "stm32_def.h" #if defined(USE_HALV2_DRIVER) -#error "USB library is not yet compatible with HALv2 driver." +#if !defined(STM32C5xx) +#error "USB library is not yet compatible with this HALv2 driver." +#endif + +/* STM32C5 uses the HAL v2 USB DRD FS PCD. Keep the legacy USB name and + * PMA buffer-kind names available to the common endpoint configuration. */ +#define USB USB_DRD_FS +#define PCD_SNG_BUF HAL_PCD_SNG_BUF +#define PCD_DBL_BUF HAL_PCD_DBL_BUF +#define USB_IRQn USB_DRD_FS_IRQn +#define USB_IRQHandler USB_DRD_FS_IRQHandler #else #if !defined(USB_BASE) && !defined(USB_OTG_DEVICE_BASE) #error "This board does not support USB! Select 'None' in the 'Tools->USB interface' menu" diff --git a/libraries/USBDevice/src/cdc/usbd_cdc.c b/libraries/USBDevice/src/cdc/usbd_cdc.c index d2e8cf7dfb..803476aca9 100644 --- a/libraries/USBDevice/src/cdc/usbd_cdc.c +++ b/libraries/USBDevice/src/cdc/usbd_cdc.c @@ -701,7 +701,11 @@ static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_CDC_HandleTypeDef *hcdc; +#if defined(USE_HALV2_DRIVER) + hal_pcd_handle_t *hpcd = (hal_pcd_handle_t *)pdev->pData; +#else PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData; +#endif if (pdev->pClassDataCmsit[pdev->classId] == NULL) { return (uint8_t)USBD_FAIL; @@ -710,7 +714,13 @@ static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) && - ((pdev->ep_in[epnum & 0xFU].total_length % hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U)) { + ((pdev->ep_in[epnum & 0xFU].total_length % +#if defined(USE_HALV2_DRIVER) + hpcd->in_ep[epnum & 0xFU].max_packet +#else + hpcd->IN_ep[epnum & 0xFU].maxpacket +#endif + ) == 0U)) { /* Update the packet total length */ pdev->ep_in[epnum & 0xFU].total_length = 0U; diff --git a/libraries/USBDevice/src/usbd_conf.c b/libraries/USBDevice/src/usbd_conf.c index 8b0d8184aa..85398b8bea 100644 --- a/libraries/USBDevice/src/usbd_conf.c +++ b/libraries/USBDevice/src/usbd_conf.c @@ -16,7 +16,7 @@ * ****************************************************************************** */ -#ifdef USBCON +#if defined(USBCON) && !defined(USE_HALV2_DRIVER) /* Includes ------------------------------------------------------------------*/ #include "usbd_core.h" #include "usbd_if.h" @@ -718,6 +718,5 @@ void USBD_LL_Delay(uint32_t Delay) HAL_Delay(Delay); } #endif /* HAL_PCD_MODULE_ENABLED */ -#endif /* USBCON */ +#endif /* USBCON && !USE_HALV2_DRIVER */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - diff --git a/libraries/USBDevice/src/usbd_conf_c5.c b/libraries/USBDevice/src/usbd_conf_c5.c new file mode 100644 index 0000000000..80f1931d46 --- /dev/null +++ b/libraries/USBDevice/src/usbd_conf_c5.c @@ -0,0 +1,251 @@ +/** + ****************************************************************************** + * @file usbd_conf_c5.c + * @brief STM32C5 HAL v2 USB device low-level adapter. + ****************************************************************************** + */ + +#if defined(USBCON) && defined(USE_HALV2_DRIVER) && defined(STM32C5xx) + +#include "usbd_core.h" +#include "usbd_if.h" +#include "usbd_ep_conf.h" + +#ifndef USE_HAL_PCD_MODULE +#error "USE_HAL_PCD_MODULE is required" +#endif + +static hal_pcd_handle_t g_hpcd; +static USBD_HandleTypeDef *g_pdev; +static uint8_t g_stalled_in; +static uint8_t g_stalled_out; + +static void USBD_C5_ErrorHandler(void) +{ + Error_Handler(); +} + +static void USBD_C5_ConfigPinsAndIrq(void) +{ + /* USB DRD FS owns PA11/PA12 and configures these fixed USB pins itself + * during peripheral initialization. Do not configure a GPIO alternate + * function here: C5 USB differs from the older USB device IPs. */ + + HAL_RCC_USB_EnableClock(); + HAL_CORTEX_NVIC_SetPriority(USB_DRD_FS_IRQn, USBD_IRQ_PRIO, USBD_IRQ_SUBPRIO); + HAL_CORTEX_NVIC_EnableIRQ(USB_DRD_FS_IRQn); +} + +void HAL_PCD_SetupStageCallback(hal_pcd_handle_t *hpcd) +{ + USBD_LL_SetupStage(g_pdev, (uint8_t *)hpcd->setup); +} + +void HAL_PCD_DataOutStageCallback(hal_pcd_handle_t *hpcd, uint8_t epnum) +{ + USBD_LL_DataOutStage(g_pdev, epnum, hpcd->out_ep[epnum].p_xfer_buffer); +} + +void HAL_PCD_DataInStageCallback(hal_pcd_handle_t *hpcd, uint8_t epnum) +{ + USBD_LL_DataInStage(g_pdev, epnum, hpcd->in_ep[epnum].p_xfer_buffer); +} + +void HAL_PCD_SofCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_SOF(g_pdev); +} + +void HAL_PCD_ResetCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_Reset(g_pdev); + USBD_LL_SetSpeed(g_pdev, USBD_SPEED_FULL); +} + +void HAL_PCD_SuspendCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_Suspend(g_pdev); +} + +void HAL_PCD_ResumeCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_Resume(g_pdev); +} + +void HAL_PCD_ISOOUTIncompleteCallback(hal_pcd_handle_t *hpcd, uint8_t epnum) +{ + (void)hpcd; + USBD_LL_IsoOUTIncomplete(g_pdev, epnum); +} + +void HAL_PCD_ISOINIncompleteCallback(hal_pcd_handle_t *hpcd, uint8_t epnum) +{ + (void)hpcd; + USBD_LL_IsoINIncomplete(g_pdev, epnum); +} + +void HAL_PCD_ConnectCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_DevConnected(g_pdev); +} + +void HAL_PCD_DisconnectCallback(hal_pcd_handle_t *hpcd) +{ + (void)hpcd; + USBD_LL_DevDisconnected(g_pdev); +} + +void USB_DRD_FS_IRQHandler(void) +{ + HAL_PCD_IRQHandler(&g_hpcd); +} + +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) +{ + hal_pcd_config_t config = { + .dma_enable = HAL_PCD_DMA_DISABLED, + .pcd_speed = HAL_PCD_SPEED_FS, + .phy_interface = HAL_PCD_PHY_EMBEDDED_FS, + .sof_enable = HAL_PCD_SOF_DISABLED, + .lpm_enable = HAL_PCD_LPM_DISABLED, + .battery_charging_enable = HAL_PCD_BCD_DISABLED, + .vbus_sensing_enable = HAL_PCD_VBUS_SENSE_DISABLED, + .bulk_doublebuffer_enable = HAL_PCD_BULK_DB_DISABLED, + }; + + USBD_reenumerate(); + USBD_C5_ConfigPinsAndIrq(); + + g_pdev = pdev; + g_stalled_in = 0U; + g_stalled_out = 0U; + pdev->pData = &g_hpcd; + + if (HAL_PCD_Init(&g_hpcd, HAL_PCD_DRD_FS) != HAL_OK) { + USBD_C5_ErrorHandler(); + } + if (HAL_PCD_SetConfig(&g_hpcd, &config) != HAL_OK) { + USBD_C5_ErrorHandler(); + } + + for (uint32_t i = 0U; i < (DEV_NUM_EP + 1U); i++) { + if (HAL_PCD_PMAConfig(&g_hpcd, ep_def[i].ep_adress, ep_def[i].ep_kind, + ep_def[i].ep_size) != HAL_OK) { + USBD_C5_ErrorHandler(); + } + } + + return USBD_OK; +} + +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) +{ + (void)pdev; + HAL_CORTEX_NVIC_DisableIRQ(USB_DRD_FS_IRQn); + HAL_PCD_DeInit(&g_hpcd); + HAL_RCC_USB_DisableClock(); + g_pdev = NULL; + return USBD_OK; +} + +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) +{ + (void)pdev; + return (HAL_PCD_Start(&g_hpcd) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) +{ + (void)pdev; + return (HAL_PCD_Stop(&g_hpcd) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t ep_type, uint16_t ep_mps) +{ + (void)pdev; + return (HAL_PCD_OpenEndpoint(&g_hpcd, ep_addr, ep_mps, + (hal_pcd_ep_type_t)ep_type) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + (void)pdev; + return (HAL_PCD_CloseEndpoint(&g_hpcd, ep_addr) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + (void)pdev; + return (HAL_PCD_FlushEndpoint(&g_hpcd, ep_addr) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + uint8_t mask = (uint8_t)(1U << (ep_addr & 0x0FU)); + (void)pdev; + if ((ep_addr & 0x80U) != 0U) { + g_stalled_in |= mask; + } else { + g_stalled_out |= mask; + } + return (HAL_PCD_SetEndpointStall(&g_hpcd, ep_addr) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + uint8_t mask = (uint8_t)(1U << (ep_addr & 0x0FU)); + (void)pdev; + if ((ep_addr & 0x80U) != 0U) { + g_stalled_in &= (uint8_t)~mask; + } else { + g_stalled_out &= (uint8_t)~mask; + } + return (HAL_PCD_ClearEndpointStall(&g_hpcd, ep_addr) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + uint8_t mask = (uint8_t)(1U << (ep_addr & 0x0FU)); + (void)pdev; + return ((ep_addr & 0x80U) != 0U) ? ((g_stalled_in & mask) != 0U) : + ((g_stalled_out & mask) != 0U); +} + +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +{ + (void)pdev; + return (HAL_PCD_SetDeviceAddress(&g_hpcd, dev_addr) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t *pbuf, uint32_t size) +{ + (void)pdev; + return (HAL_PCD_SetEndpointTransmit(&g_hpcd, ep_addr, pbuf, size) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t *pbuf, uint32_t size) +{ + (void)pdev; + return (HAL_PCD_SetEndpointReceive(&g_hpcd, ep_addr, pbuf, size) == HAL_OK) ? USBD_OK : USBD_FAIL; +} + +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + (void)pdev; + return HAL_PCD_EP_GetRxCount(&g_hpcd, ep_addr); +} + +void USBD_LL_Delay(uint32_t delay) +{ + HAL_Delay(delay); +} + +#endif /* USBCON && USE_HALV2_DRIVER && STM32C5xx */ diff --git a/libraries/USBDevice/src/usbd_if.c b/libraries/USBDevice/src/usbd_if.c index fb76a5a778..fde97a8b13 100644 --- a/libraries/USBDevice/src/usbd_if.c +++ b/libraries/USBDevice/src/usbd_if.c @@ -144,6 +144,13 @@ WEAK void USBD_reenumerate(void) #else digitalWriteFast(USBD_PULLUP_CONTROL_PINNAME, USBD_ATTACH_LEVEL); #endif /* defined(USBD_PULLUP_CONTROL_FLOATING) */ +#elif defined(STM32C5xx) && defined(USE_HALV2_DRIVER) + /* HAL v2 PCD owns the internal pull-up but is not initialized yet when + * this hook runs. Briefly pulling D+ low provides the same detach window. */ + pin_function(PA_12, STM_PIN_DATA(STM_MODE_OUTPUT_PP, LL_GPIO_PULL_NO, 0)); + digitalWriteFast(PA_12, LOW); + delay(USBD_ENUM_DELAY); + pin_function(PA_12, STM_PIN_DATA(STM_MODE_INPUT, LL_GPIO_PULL_NO, 0)); #elif defined(USBD_HAVE_INTERNAL_PULLUPS) #if defined(SYSCFG_PMC_USB_PU) /** From da8a90435516a8238d05d329903d9a5581f23ef0 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 10 Aug 2026 15:55:41 +0800 Subject: [PATCH 03/17] feat(usb): add optional CDC line-coding hook --- libraries/USBDevice/inc/usbd_cdc_if.h | 3 +++ libraries/USBDevice/src/cdc/usbd_cdc_if.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/USBDevice/inc/usbd_cdc_if.h b/libraries/USBDevice/inc/usbd_cdc_if.h index 1d3f8b91ff..5f1459388a 100644 --- a/libraries/USBDevice/inc/usbd_cdc_if.h +++ b/libraries/USBDevice/inc/usbd_cdc_if.h @@ -59,6 +59,9 @@ uint8_t CDC_getStopBits(void); uint8_t CDC_getParity(void); uint8_t CDC_getDataBits(void); +/* Optional board hook invoked after the host changes the CDC line coding. */ +void CDC_LineCodingChanged(uint32_t bitrate); + #ifdef __cplusplus } #endif diff --git a/libraries/USBDevice/src/cdc/usbd_cdc_if.c b/libraries/USBDevice/src/cdc/usbd_cdc_if.c index 922b7d57e3..4b67022be5 100644 --- a/libraries/USBDevice/src/cdc/usbd_cdc_if.c +++ b/libraries/USBDevice/src/cdc/usbd_cdc_if.c @@ -89,6 +89,12 @@ USBD_CDC_LineCodingTypeDef linecoding = { 0x08 /* nb. of bits 8*/ }; +/* Boards that need a CDC line-coding side effect can override this hook. */ +WEAK void CDC_LineCodingChanged(uint32_t bitrate) +{ + (void)bitrate; +} + /* Private functions ---------------------------------------------------------*/ /** @@ -175,6 +181,7 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) linecoding.format = pbuf[4]; linecoding.paritytype = pbuf[5]; linecoding.datatype = pbuf[6]; + CDC_LineCodingChanged(linecoding.bitrate); break; case CDC_GET_LINE_CODING: @@ -406,4 +413,3 @@ uint8_t CDC_getDataBits(void) #endif /* USBD_USE_CDC */ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - From 6d7eeb2b985ca303264eebc59b06a7b0f6ba5f36 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 10 Aug 2026 15:55:59 +0800 Subject: [PATCH 04/17] feat(upload): add generic UF2 uploader recipe --- platform.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platform.txt b/platform.txt index 702f24c994..8ac799d56f 100644 --- a/platform.txt +++ b/platform.txt @@ -212,6 +212,15 @@ tools.massStorageCopy.upload.params.verbose= tools.massStorageCopy.upload.params.quiet= tools.massStorageCopy.upload.pattern="{tools_bin_path}/{cmd}" {upload.verbose} -I "{build.path}/{build.project_name}.bin" -O "{node}" +# Upload a UF2 image through a CDC 1200-bps touch and a UF2 mass-storage +# bootloader. Board-specific address, family ID, volume label and size limits +# are supplied by boards.txt. +tools.uf2upload.cmd=uf2upload +tools.uf2upload.cmd.windows=uf2upload.exe +tools.uf2upload.upload.params.verbose= +tools.uf2upload.upload.params.quiet= +tools.uf2upload.upload.pattern="{tools_bin_path}/{cmd}" --input "{build.path}/{build.project_name}.bin" --port "{serial.port}" --volume "{upload.uf2.volume}" --address {upload.uf2.address} --family {upload.uf2.family} --max-size {upload.maximum_size} --timeout {upload.uf2.timeout} + # STM32CubeProgrammer upload tools.stm32CubeProg.path={runtime.tools.STM32Tools.path} tools.stm32CubeProg.cmd=stm32CubeProg.sh From af81304b93388a6d8b5ad1fa43b69206b33a1c91 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 10 Aug 2026 15:56:09 +0800 Subject: [PATCH 05/17] feat(xiao): add STM32C5 board variant --- boards.txt | 35 ++++ .../ldscript_XIAO_STM32C5.ld | 174 ++++++++++++++++++ .../variant_XIAO_STM32C5.cpp | 100 ++++++++++ .../variant_XIAO_STM32C5.h | 86 +++++++++ 4 files changed, 395 insertions(+) create mode 100644 variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/ldscript_XIAO_STM32C5.ld create mode 100644 variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp create mode 100644 variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h diff --git a/boards.txt b/boards.txt index 6c3dfcc648..9698863bea 100644 --- a/boards.txt +++ b/boards.txt @@ -2167,6 +2167,41 @@ GenC0.menu.upload_method.OpenOCDDapLink.upload.tool=openocd_upload GenC0.menu.upload_method.OpenOCDDapLink.debug.server.openocd.scripts.0=interface/cmsis-dap.cfg GenC0.menu.upload_method.OpenOCDDapLink.debug.server.openocd.scripts.1={runtime.platform.path}/debugger/select_swd.cfg +################################################################################ +# Seeed XIAO STM32C5 +XIAO_STM32C5.name=Seeed XIAO STM32C5 + +XIAO_STM32C5.build.core=arduino +XIAO_STM32C5.build.board=XIAO_STM32C5 +XIAO_STM32C5.build.variant=STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U) +XIAO_STM32C5.build.variant_h=variant_XIAO_STM32C5.h +XIAO_STM32C5.build.ldscript=ldscript_XIAO_STM32C5.ld +XIAO_STM32C5.build.st_extra_flags=-D{build.product_line} -DHSE_VALUE=48000000U -DUSBD_SELF_POWERED=1 -DUSBD_MAX_POWER=50 {build.enable_usb} {build.xSerial} +XIAO_STM32C5.build.mcu=cortex-m33 +XIAO_STM32C5.build.fpu=-mfpu=fpv5-sp-d16 +XIAO_STM32C5.build.float-abi=-mfloat-abi=hard +XIAO_STM32C5.build.series=STM32C5xx +XIAO_STM32C5.build.product_line=STM32C5A3xx +XIAO_STM32C5.build.hal=-DUSE_HALV2_DRIVER +XIAO_STM32C5.build.flash_offset=0x8000 +XIAO_STM32C5.upload.maximum_size=1015808 +XIAO_STM32C5.upload.maximum_data_size=262144 +XIAO_STM32C5.upload.tool=uf2upload +XIAO_STM32C5.upload.protocol=serial +XIAO_STM32C5.upload.uf2.volume=XIAOC5BOOT +XIAO_STM32C5.upload.uf2.address=0x08008000 +XIAO_STM32C5.upload.uf2.family=0x00C5C5C5 +XIAO_STM32C5.upload.uf2.timeout=10000 +XIAO_STM32C5.debug.svd_file={runtime.tools.STM32_SVD.path}/svd/STM32C5xx/STM32C5A3.svd +XIAO_STM32C5.vid.0=0x2886 +XIAO_STM32C5.pid.0=0x80C5 + +# USB CDC is the user-facing default. The temporary None option permits +# non-USB phase-1 validation until C5 HAL v2 USB support is implemented. +XIAO_STM32C5.menu.usb.CDC=CDC (Serial) +XIAO_STM32C5.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC +XIAO_STM32C5.menu.usb.none=None + ################################################################################ # Generic C5 GenC5.name=Generic STM32C5 series diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/ldscript_XIAO_STM32C5.ld b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/ldscript_XIAO_STM32C5.ld new file mode 100644 index 0000000000..a4da2f60fe --- /dev/null +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/ldscript_XIAO_STM32C5.ld @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2026, Seeed Technology Co., Ltd. + * SPDX-License-Identifier: BSD-3-Clause + * + * The application starts after the 32 KiB TinyUF2 bootloader. Memory sizes are + * supplied by boards.txt through LD_MAX_SIZE and LD_MAX_DATA_SIZE. + */ +ENTRY(Reset_Handler) + +HEAP_SIZE = 0x2000; +STACK_SIZE = 0x2000; + +MEMORY +{ + ROM (rx) : org = 0x08000000 + LD_FLASH_OFFSET, len = LD_MAX_SIZE - LD_FLASH_OFFSET + /* TinyUF2 uses the final SRAM word for the 1200-bps reset handoff. */ + RAM (xrw) : org = 0x20000000, len = LD_MAX_DATA_SIZE - 4 +} + +SECTIONS +{ + .vectors : + { + . = ALIGN(8); + KEEP(*(.vectors)); + . = ALIGN(8); + } > ROM + + .text : + { + . = ALIGN(8); + *(.text); + *(.text*); + *(.glue_7); + *(.glue_7t); + *(.eh_frame); + KEEP(*(.init)); + KEEP(*(.fini)); + . = ALIGN(8); + _etext = .; + } > ROM + + .rodata : + { + . = ALIGN(8); + *(.rodata); + *(.rodata*); + . = ALIGN(8); + } > ROM + + .ARM.extab (READONLY) : + { + . = ALIGN(8); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(8); + } > ROM + + .ARM (READONLY) : + { + . = ALIGN(8); + __exidx_start = .; + *(.ARM.exidx*); + __exidx_end = .; + . = ALIGN(8); + } > ROM + + .preinit_array (READONLY) : + { + . = ALIGN(8); + PROVIDE_HIDDEN(__preinit_array_start = .); + KEEP(*(.preinit_array*)); + PROVIDE_HIDDEN(__preinit_array_end = .); + . = ALIGN(8); + } > ROM + + .init_array (READONLY) : + { + . = ALIGN(8); + PROVIDE_HIDDEN(__init_array_start = .); + KEEP(*(SORT(.init_array.*))); + KEEP(*(.init_array*)); + PROVIDE_HIDDEN(__init_array_end = .); + . = ALIGN(8); + } > ROM + + .fini_array (READONLY) : + { + . = ALIGN(8); + PROVIDE_HIDDEN(__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))); + KEEP(*(.fini_array*)); + PROVIDE_HIDDEN(__fini_array_end = .); + . = ALIGN(8); + } > ROM + + .copy.table (READONLY) : + { + . = ALIGN(8); + __copy_table_start__ = .; + LONG(LOADADDR(.data)); + LONG(ADDR(.data)); + LONG(SIZEOF(.data) / 4); + __copy_table_end__ = .; + } > ROM + + .zero.table (READONLY) : + { + . = ALIGN(8); + __zero_table_start__ = .; + LONG(ADDR(.bss)); + LONG(SIZEOF(.bss) / 4); + __zero_table_end__ = .; + } > ROM + + .data : + { + . = ALIGN(8); + _sidata = LOADADDR(.data); + __data_start__ = .; + _sdata = .; + *(.data); + *(.data*); + . = ALIGN(8); + _edata = .; + } > RAM AT> ROM + + .bss : + { + . = ALIGN(8); + _sbss = .; + __bss_start__ = _sbss; + *(.bss); + *(.bss*); + *(COMMON); + . = ALIGN(8); + _ebss = .; + __bss_end__ = _ebss; + } > RAM + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + _heap_start = .; + . += HEAP_SIZE; + . = ALIGN(8); + _heap_end = .; + __HeapLimit = .; + } > RAM + + .stack (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . += STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + _estack = .; + __stack = .; + } > RAM + + /DISCARD/ : + { + libc.a(*); + libm.a(*); + libgcc.a(*); + } + + .ARM.attributes 0 : + { + *(.ARM.attributes) + } +} diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp new file mode 100644 index 0000000000..79d8d092e9 --- /dev/null +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2026, Seeed Technology Co., Ltd. + * SPDX-License-Identifier: BSD-3-Clause + */ +#if defined(ARDUINO_XIAO_STM32C5) + +#include "pins_arduino.h" + +const PinName digitalPin[] = { + PA_0, // D0 / A0 + PA_1, // D1 / A1 + PA_2, // D2 / A2 + PA_3, // D3 / A3 + PB_7, // D4 / I2C1_SDA + PB_6, // D5 / I2C1_SCL + PA_9, // D6 / USART1_TX + PA_10, // D7 / USART1_RX + PA_15, // D8 + PB_0, // D9 + PB_15, // D10 + PB_8, // D11 / FDCAN1_RX + PB_9, // D12 / FDCAN1_TX + PB_5, // D13 / FDCAN2_RX + PB_13, // D14 / FDCAN2_TX + PB_14, // D15 / CAN_STB + PB_12 // Board LED, active low +}; + +const pin_size_t analogInputPin[] = { + D0, + D1, + D2, + D3 +}; + +/* TinyUF2 C5 (d52adcf) reserves the last SRAM word for the double-tap + * handoff. The matching application linker script excludes this word from + * the stack/heap RAM region. */ +static constexpr uintptr_t TINYUF2_HANDOFF_ADDRESS = 0x2003FFFCUL; +static constexpr uint32_t TINYUF2_ENTER_DFU_MAGIC = 0xF01669EFUL; + +extern "C" void CDC_LineCodingChanged(uint32_t bitrate) +{ + if (bitrate == 1200U) { + *reinterpret_cast(TINYUF2_HANDOFF_ADDRESS) = TINYUF2_ENTER_DFU_MAGIC; + __DSB(); + __ISB(); + NVIC_SystemReset(); + while (true) { + } + } +} + +extern "C" void SystemClock_Config(void) +{ + if (HAL_RCC_HSE_Enable(HAL_RCC_HSE_ON) != HAL_OK) { + Error_Handler(); + } + + hal_rcc_psi_config_t psi_config; + psi_config.psi_source = HAL_RCC_PSI_SRC_HSE; + psi_config.psi_ref = HAL_RCC_PSI_REF_48MHZ; + psi_config.psi_out = HAL_RCC_PSI_OUT_144MHZ; + if (HAL_RCC_PSI_SetConfig(&psi_config) != HAL_OK) { + Error_Handler(); + } + if (HAL_RCC_PSIS_Enable() != HAL_OK) { + Error_Handler(); + } + + hal_rcc_bus_clk_config_t bus_config; + bus_config.hclk_prescaler = HAL_RCC_HCLK_PRESCALER1; + bus_config.pclk1_prescaler = HAL_RCC_PCLK_PRESCALER2; + bus_config.pclk2_prescaler = HAL_RCC_PCLK_PRESCALER2; + bus_config.pclk3_prescaler = HAL_RCC_PCLK_PRESCALER2; + if (HAL_RCC_SetBusClockConfig(&bus_config) != HAL_OK) { + Error_Handler(); + } + + HAL_FLASH_ITF_SetLatency(HAL_FLASH, HAL_FLASH_ITF_LATENCY_4); + if (HAL_RCC_SetSYSCLKSource(HAL_RCC_SYSCLK_SRC_PSIS) != HAL_OK) { + Error_Handler(); + } + HAL_FLASH_ITF_SetProgrammingDelay(HAL_FLASH, HAL_FLASH_ITF_PROGRAM_DELAY_2); + if (HAL_RCC_CK48_SetKernelClkSource(HAL_RCC_CK48_CLK_SRC_HSE) != HAL_OK) { + Error_Handler(); + } + if (HAL_UpdateCoreClock() != HAL_OK) { + Error_Handler(); + } +} + +void initVariant(void) +{ + /* CAN_STB is active high. Keep the onboard transceiver out of standby. */ + pinMode(D15, OUTPUT); + digitalWrite(D15, LOW); +} + +#endif /* ARDUINO_XIAO_STM32C5 */ diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h new file mode 100644 index 0000000000..68e4d8a86c --- /dev/null +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2026, Seeed Technology Co., Ltd. + * SPDX-License-Identifier: BSD-3-Clause + */ +#pragma once + +/* XIAO connector pin numbers. */ +#define PA0 PIN_A0 +#define PA1 PIN_A1 +#define PA2 PIN_A2 +#define PA3 PIN_A3 +#define PB7 4 +#define PB6 5 +#define PA9 6 +#define PA10 7 +#define PA15 8 +#define PB0 9 +#define PB15 10 +#define PB8 11 +#define PB9 12 +#define PB5 13 +#define PB13 14 +#define PB14 15 + +/* Board-only pin: it follows the XIAO connector pins in digitalPin[]. */ +#define PB12 16 + +/* Alternate functions used by the default board peripherals. */ +#define PA9_ALT1 (PA9 | ALT1) +#define PA10_ALT1 (PA10 | ALT1) + +#define NUM_DIGITAL_PINS 17 +#define NUM_ANALOG_INPUTS 4 + +#ifndef LED_BUILTIN + #define LED_BUILTIN PB12 +#endif + +/* SPI is intentionally not advertised until the connector SPI route is fixed + * and validated on production hardware. */ +#define PIN_SPI_SS NUM_DIGITAL_PINS +#define PIN_SPI_SS1 NUM_DIGITAL_PINS +#define PIN_SPI_SS2 NUM_DIGITAL_PINS +#define PIN_SPI_SS3 NUM_DIGITAL_PINS +#define PIN_SPI_MOSI NUM_DIGITAL_PINS +#define PIN_SPI_MISO NUM_DIGITAL_PINS +#define PIN_SPI_SCK NUM_DIGITAL_PINS + +#define PIN_WIRE_SDA PB7 +#define PIN_WIRE_SCL PB6 + +#define TIMER_TONE TIM16 +#define TIMER_SERVO TIM17 + +/* Serial is USB CDC when enabled. Serial1 is the connector UART on D6/D7. */ +#define SERIAL_UART_INSTANCE 1 +#define PIN_SERIAL_TX PA9_ALT1 +#define PIN_SERIAL_RX PA10_ALT1 + +#ifndef HSE_VALUE + #define HSE_VALUE 48000000U +#endif + +/* USBDevice includes the selected variant, so these remain board-owned + * descriptor strings without adding quoted compiler flags to every recipe. */ +#ifndef USB_MANUFACTURER_STRING + #define USB_MANUFACTURER_STRING "Seeed Studio" +#endif +#ifndef USB_PRODUCT_STRING + #define USB_PRODUCT_STRING "XIAO STM32C5" +#endif + +#ifdef __cplusplus + #ifndef SERIAL_PORT_MONITOR + #define SERIAL_PORT_MONITOR Serial + #endif + #ifndef SERIAL_PORT_USBVIRTUAL + #define SERIAL_PORT_USBVIRTUAL Serial + #endif + #ifndef SERIAL_PORT_HARDWARE + #define SERIAL_PORT_HARDWARE Serial1 + #endif + #ifndef SERIAL_PORT_HARDWARE_OPEN + #define SERIAL_PORT_HARDWARE_OPEN Serial1 + #endif +#endif From f326cf143bccd630f47b1bad4b1210d67b64b15e Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 17 Aug 2026 15:19:37 +0800 Subject: [PATCH 06/17] feat(xiao): enable SPI3 pin mapping --- .../variant_XIAO_STM32C5.cpp | 6 +++--- .../variant_XIAO_STM32C5.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp index 79d8d092e9..f4ab9be6c8 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp @@ -15,9 +15,9 @@ const PinName digitalPin[] = { PB_6, // D5 / I2C1_SCL PA_9, // D6 / USART1_TX PA_10, // D7 / USART1_RX - PA_15, // D8 - PB_0, // D9 - PB_15, // D10 + PE_2, // D8 / SPI3_SCK + PB_0, // D9 / SPI3_MISO + PB_15, // D10 / SPI3_MOSI PB_8, // D11 / FDCAN1_RX PB_9, // D12 / FDCAN1_TX PB_5, // D13 / FDCAN2_RX diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h index 68e4d8a86c..673ca40ca5 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -13,7 +13,7 @@ #define PB6 5 #define PA9 6 #define PA10 7 -#define PA15 8 +#define PE2 8 #define PB0 9 #define PB15 10 #define PB8 11 @@ -36,15 +36,15 @@ #define LED_BUILTIN PB12 #endif -/* SPI is intentionally not advertised until the connector SPI route is fixed - * and validated on production hardware. */ +/* SPI3: D8/SCK (PE2), D9/MISO (PB0), D10/MOSI (PB15). + * No board-default chip-select is assigned; sketches control device CS. */ #define PIN_SPI_SS NUM_DIGITAL_PINS #define PIN_SPI_SS1 NUM_DIGITAL_PINS #define PIN_SPI_SS2 NUM_DIGITAL_PINS #define PIN_SPI_SS3 NUM_DIGITAL_PINS -#define PIN_SPI_MOSI NUM_DIGITAL_PINS -#define PIN_SPI_MISO NUM_DIGITAL_PINS -#define PIN_SPI_SCK NUM_DIGITAL_PINS +#define PIN_SPI_MOSI PB15 +#define PIN_SPI_MISO PB0 +#define PIN_SPI_SCK PE2 #define PIN_WIRE_SDA PB7 #define PIN_WIRE_SCL PB6 From 58dbf25daf13ed0b81fe182a0730fa56078a7bef Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Mon, 17 Aug 2026 19:02:23 +0800 Subject: [PATCH 07/17] fix(spi): bound HAL v2 polling transfers --- libraries/SPI/src/utility/spi_com.c | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 1778e06d80..146c8a6f84 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -20,6 +20,17 @@ extern "C" { #endif +#if defined(USE_HALV2_DRIVER) +/* HAL v2 polling APIs use HAL_GetTick() for their timeout. On the current + * Arduino C5 clock path that tick is not guaranteed to advance while polling, + * so use the Arduino microsecond clock to bound LL polling instead. */ +static bool spi_transfer_timed_out(uint32_t start_us) +{ + return (SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) + && ((uint32_t)(micros() - start_us) >= (SPI_TRANSFER_TIMEOUT * 1000UL)); +} +#endif + /* Private Functions */ /** * @brief return clock freq of an SPI instance @@ -564,6 +575,9 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff { spi_status_e ret = SPI_OK; uint32_t tickstart, size = len; +#if defined(USE_HALV2_DRIVER) + uint32_t start_us; +#endif SPI_TypeDef *_SPI = obj->spi; uint8_t *tx_buf = (uint8_t *)tx_buffer; @@ -571,6 +585,9 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff ret = SPI_ERROR; } else { tickstart = HAL_GetTick(); +#if defined(USE_HALV2_DRIVER) + start_us = micros(); +#endif #if defined(SPI_CR2_TSIZE) /* Start transfer */ @@ -581,14 +598,32 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff while (size--) { #if defined(SPI_SR_TXP) +#if defined(USE_HALV2_DRIVER) + while (!LL_SPI_IsActiveFlag_TXP(_SPI)) { + if (spi_transfer_timed_out(start_us)) { + ret = SPI_TIMEOUT; + goto spi_transfer_end; + } + } +#else while (!LL_SPI_IsActiveFlag_TXP(_SPI)); +#endif #else while (!LL_SPI_IsActiveFlag_TXE(_SPI)); #endif LL_SPI_TransmitData8(_SPI, tx_buf ? *tx_buf++ : 0XFF); #if defined(SPI_SR_RXP) +#if defined(USE_HALV2_DRIVER) + while (!LL_SPI_IsActiveFlag_RXP(_SPI)) { + if (spi_transfer_timed_out(start_us)) { + ret = SPI_TIMEOUT; + goto spi_transfer_end; + } + } +#else while (!LL_SPI_IsActiveFlag_RXP(_SPI)); +#endif #else while (!LL_SPI_IsActiveFlag_RXNE(_SPI)); #endif @@ -598,17 +633,24 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff LL_SPI_ReceiveData8(_SPI); } if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) && +#if defined(USE_HALV2_DRIVER) + (spi_transfer_timed_out(start_us))) { +#else (HAL_GetTick() - tickstart >= SPI_TRANSFER_TIMEOUT)) { +#endif ret = SPI_TIMEOUT; break; } } #if defined(SPI_IFCR_EOTC) +spi_transfer_end: // Add a delay before disabling SPI otherwise last-bit/last-clock may be truncated // See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294 // Computed delay is half SPI clock - delayMicroseconds(obj->disable_delay); + if (ret == SPI_OK) { + delayMicroseconds(obj->disable_delay); + } /* Close transfer */ /* Clear flags */ From 89bbefa2dc28b403ec211b0783a0cb7f99c453e6 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 09:51:16 +0800 Subject: [PATCH 08/17] fix(spi): initialize bus on begin --- libraries/SPI/src/SPI.cpp | 6 +++--- libraries/SPI/src/SPI.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 2a23c0ef31..7d328b8469 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -13,9 +13,9 @@ SPIClass SPI; -void SPIClass::configSpi(const SPISettings &settings) +void SPIClass::configSpi(const SPISettings &settings, bool force) { - if (_spiSettings != settings) { + if (force || _spiSettings != settings) { _spiSettings = settings; uint32_t clock = settings.getClockFreq(); @@ -79,7 +79,7 @@ void SPIClass::begin(SPIBusMode busMode) SPI_MODE0, busMode ); - configSpi(defaultSettings); + configSpi(defaultSettings, true); } /** diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 0560a0b7f0..279b27cad5 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -135,7 +135,7 @@ class SPIClass : public HardwareSPI { /* Current SPISettings */ SPISettings _spiSettings = SPISettings(); - void configSpi(const SPISettings &settings); + void configSpi(const SPISettings &settings, bool force = false); }; extern SPIClass SPI; From e1884f25e137df9fbdf28d6c46164c085b6212d7 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 09:51:17 +0800 Subject: [PATCH 09/17] fix(xiao): select SPI3 alternate function for MOSI --- .../C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h index 673ca40ca5..11cd30f344 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -42,7 +42,7 @@ #define PIN_SPI_SS1 NUM_DIGITAL_PINS #define PIN_SPI_SS2 NUM_DIGITAL_PINS #define PIN_SPI_SS3 NUM_DIGITAL_PINS -#define PIN_SPI_MOSI PB15 +#define PIN_SPI_MOSI PB_15_ALT2 #define PIN_SPI_MISO PB0 #define PIN_SPI_SCK PE2 From 178420b70393f2e7730195904b98a1fd64b3448c Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 11:00:27 +0800 Subject: [PATCH 10/17] fix(usb): limit CDC transmit blocks to packet size --- libraries/USBDevice/src/cdc/cdc_queue.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/USBDevice/src/cdc/cdc_queue.c b/libraries/USBDevice/src/cdc/cdc_queue.c index 2d2330c195..50d3031a5e 100644 --- a/libraries/USBDevice/src/cdc/cdc_queue.c +++ b/libraries/USBDevice/src/cdc/cdc_queue.c @@ -85,6 +85,11 @@ uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, } else { *size = CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->read; } + + /* Limit the queued transaction to one endpoint packet. */ + if (*size > CDC_QUEUE_MAX_PACKET_SIZE) { + *size = CDC_QUEUE_MAX_PACKET_SIZE; + } queue->reserved = *size; return &queue->buffer[queue->read]; } From 73e186f1af8dfde38614f9480b95e76b03d37b19 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 11:09:29 +0800 Subject: [PATCH 11/17] fix(usb): use non-overlapping C5 CDC PMA buffers --- libraries/USBDevice/inc/usbd_ep_conf.h | 13 ++++++++++++- libraries/USBDevice/src/usbd_ep_conf.c | 3 +-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/USBDevice/inc/usbd_ep_conf.h b/libraries/USBDevice/inc/usbd_ep_conf.h index 354b6f4d0c..b305b64e4f 100644 --- a/libraries/USBDevice/inc/usbd_ep_conf.h +++ b/libraries/USBDevice/inc/usbd_ep_conf.h @@ -69,10 +69,21 @@ typedef struct { #ifdef USBD_USE_CDC #define PMA_CDC_OUT_BASE (PMA_EP0_IN_ADDR + USB_MAX_EP0_SIZE) +#if defined(STM32C5xx) +/* + * The C5 USB DRD FS peripheral is used with bulk double buffering disabled. + * Keep each CDC endpoint in its own 64-byte PMA area; in particular, the + * interrupt IN endpoint must not overlap the bulk IN data buffer. + */ +#define PMA_CDC_OUT_ADDR PMA_CDC_OUT_BASE +#define PMA_CDC_IN_ADDR (PMA_CDC_OUT_BASE + USB_FS_MAX_PACKET_SIZE) +#define PMA_CDC_CMD_ADDR (PMA_CDC_IN_ADDR + USB_FS_MAX_PACKET_SIZE) +#else #define PMA_CDC_OUT_ADDR ((PMA_CDC_OUT_BASE + USB_FS_MAX_PACKET_SIZE) | \ (PMA_CDC_OUT_BASE << 16U)) #define PMA_CDC_IN_ADDR (PMA_CDC_OUT_BASE + USB_FS_MAX_PACKET_SIZE * 2) #define PMA_CDC_CMD_ADDR (PMA_CDC_IN_ADDR + CDC_CMD_PACKET_SIZE) +#endif #endif /* USBD_USE_CDC */ #ifdef USBD_USE_HID_COMPOSITE #define PMA_MOUSE_IN_ADDR (PMA_EP0_IN_ADDR + HID_MOUSE_EPIN_SIZE) @@ -86,4 +97,4 @@ extern const ep_desc_t ep_def[DEV_NUM_EP + 1]; #endif /* USBCON */ #endif /* __USBD_EP_CONF_H */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/libraries/USBDevice/src/usbd_ep_conf.c b/libraries/USBDevice/src/usbd_ep_conf.c index d872acca5f..8759e49fda 100644 --- a/libraries/USBDevice/src/usbd_ep_conf.c +++ b/libraries/USBDevice/src/usbd_ep_conf.c @@ -37,7 +37,7 @@ const ep_desc_t ep_def[] = { #else {0x00, PMA_EP0_OUT_ADDR, PCD_SNG_BUF}, {0x80, PMA_EP0_IN_ADDR, PCD_SNG_BUF}, -#ifndef USBD_CDC_USE_SINGLE_BUFFER +#if !defined(STM32C5xx) && !defined(USBD_CDC_USE_SINGLE_BUFFER) {CDC_OUT_EP, PMA_CDC_OUT_ADDR, PCD_DBL_BUF}, #else {CDC_OUT_EP, PMA_CDC_OUT_ADDR, PCD_SNG_BUF}, @@ -72,4 +72,3 @@ const ep_desc_t ep_def[] = { #endif /* HAL_PCD_MODULE_ENABLED && USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - From 12117677ded960325b3f1dde4a47f2cf1e1c9ea0 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 15:34:09 +0800 Subject: [PATCH 12/17] fix(xiao): keep SPI3 MOSI in board pin namespace --- libraries/SPI/src/utility/spi_com.c | 3 +++ .../C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 146c8a6f84..52c6160843 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -578,6 +578,9 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff #if defined(USE_HALV2_DRIVER) uint32_t start_us; #endif + if (obj == NULL || obj->spi == NP) { + return SPI_ERROR; + } SPI_TypeDef *_SPI = obj->spi; uint8_t *tx_buf = (uint8_t *)tx_buffer; diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h index 11cd30f344..a697b03a4f 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -42,7 +42,7 @@ #define PIN_SPI_SS1 NUM_DIGITAL_PINS #define PIN_SPI_SS2 NUM_DIGITAL_PINS #define PIN_SPI_SS3 NUM_DIGITAL_PINS -#define PIN_SPI_MOSI PB_15_ALT2 +#define PIN_SPI_MOSI (PB15 | ALT2) #define PIN_SPI_MISO PB0 #define PIN_SPI_SCK PE2 From 69d48fe2136ddb00972eebbadefdda0f5da8a7a7 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Tue, 18 Aug 2026 16:50:14 +0800 Subject: [PATCH 13/17] feat(xiao): expose onboard IMU control pins --- .../C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp | 6 +++++- .../C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp index f4ab9be6c8..f88a9d4323 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp @@ -23,7 +23,11 @@ const PinName digitalPin[] = { PB_5, // D13 / FDCAN2_RX PB_13, // D14 / FDCAN2_TX PB_14, // D15 / CAN_STB - PB_12 // Board LED, active low + PB_12, // Board LED, active low + PB_3, // Onboard IMU / I2C2_SCL + PB_4, // Onboard IMU / I2C2_SDA + PC_13, // Onboard IMU / INT1 + PA_8 // Onboard IMU heater / TIM1_CH1 }; const pin_size_t analogInputPin[] = { diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h index a697b03a4f..e00b051c78 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -22,14 +22,18 @@ #define PB13 14 #define PB14 15 -/* Board-only pin: it follows the XIAO connector pins in digitalPin[]. */ +/* Board-only pins: they follow the XIAO connector pins in digitalPin[]. */ #define PB12 16 +#define PIN_IMU_SCL 17 // PB3 / I2C2_SCL +#define PIN_IMU_SDA 18 // PB4 / I2C2_SDA +#define PIN_IMU_INT1 19 // PC13 / LSM6DS3TR-C INT1 +#define PIN_IMU_HEATER 20 // PA8 / TIM1_CH1 /* Alternate functions used by the default board peripherals. */ #define PA9_ALT1 (PA9 | ALT1) #define PA10_ALT1 (PA10 | ALT1) -#define NUM_DIGITAL_PINS 17 +#define NUM_DIGITAL_PINS 21 #define NUM_ANALOG_INPUTS 4 #ifndef LED_BUILTIN From f084faa12d56177d5d4394df117c84e58a13c0e7 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Wed, 19 Aug 2026 14:07:51 +0800 Subject: [PATCH 14/17] fix(usb): generalize HAL v2 device adapter --- libraries/SrcWrapper/inc/stm32_def.h | 6 ++- libraries/USBDevice/inc/usbd_conf.h | 16 +++----- .../src/{usbd_conf_c5.c => usbd_confv2.c} | 38 ++++++++++--------- 3 files changed, 31 insertions(+), 29 deletions(-) rename libraries/USBDevice/src/{usbd_conf_c5.c => usbd_confv2.c} (87%) diff --git a/libraries/SrcWrapper/inc/stm32_def.h b/libraries/SrcWrapper/inc/stm32_def.h index e057418c0c..f63b83de26 100644 --- a/libraries/SrcWrapper/inc/stm32_def.h +++ b/libraries/SrcWrapper/inc/stm32_def.h @@ -203,11 +203,13 @@ __STATIC_INLINE void LL_RTC_SetBinMixBCDU(RTC_TypeDef *RTCx, uint32_t BinMixBcdU } #endif // STM32U0xx -/* STM32G0xx, STM32U0xx and some STM32U5xx defined USB_DRD_FS */ +/* Some STM32 series define USB_DRD_FS instead of the legacy USB instance. */ #if !defined(USB) && defined(USB_DRD_FS) #define USB USB_DRD_FS #define PinMap_USB PinMap_USB_DRD_FS - #if defined(STM32H5xx) || defined(STM32U0xx) ||\ + #if defined(STM32C5xx) + #define USB_BASE USB_DRD_FS_BASE + #elif defined(STM32H5xx) || defined(STM32U0xx) ||\ defined(STM32U3xx) || defined(STM32U5xx) #define USB_BASE USB_DRD_BASE #if !defined(__HAL_RCC_USB_CLK_ENABLE) diff --git a/libraries/USBDevice/inc/usbd_conf.h b/libraries/USBDevice/inc/usbd_conf.h index 1f19cd33ec..15d0d35341 100644 --- a/libraries/USBDevice/inc/usbd_conf.h +++ b/libraries/USBDevice/inc/usbd_conf.h @@ -31,17 +31,15 @@ extern "C" { #if defined(USE_HALV2_DRIVER) #if !defined(STM32C5xx) -#error "USB library is not yet compatible with this HALv2 driver." +#warning "USB device support is currently implemented only for STM32C5xx HAL v2." +#endif #endif -/* STM32C5 uses the HAL v2 USB DRD FS PCD. Keep the legacy USB name and - * PMA buffer-kind names available to the common endpoint configuration. */ -#define USB USB_DRD_FS +#if defined(STM32C5xx) #define PCD_SNG_BUF HAL_PCD_SNG_BUF #define PCD_DBL_BUF HAL_PCD_DBL_BUF -#define USB_IRQn USB_DRD_FS_IRQn -#define USB_IRQHandler USB_DRD_FS_IRQHandler -#else +#endif + #if !defined(USB_BASE) && !defined(USB_OTG_DEVICE_BASE) #error "This board does not support USB! Select 'None' in the 'Tools->USB interface' menu" #endif @@ -50,8 +48,6 @@ extern "C" { #endif #if !defined(USB_BASE) && !defined(USB_OTG_FS) && defined(USB_OTG_HS) && !defined(USE_USB_HS) #error "This board support only USB High Speed! Select 'High Speed' or 'High Speed in Full Speed mode' in the 'Tools->USB interface' menu" -#endif - #endif #include #include @@ -87,7 +83,7 @@ extern "C" { #elif defined(STM32G0B1xx) || defined(STM32G0C1xx) #define USB_IRQn USB_UCPD1_2_IRQn #define USB_IRQHandler USB_UCPD1_2_IRQHandler -#elif defined(STM32C0xx) || defined(STM32H5xx) || defined(STM32U0xx) +#elif defined(STM32C0xx) || defined(STM32C5xx) || defined(STM32H5xx) || defined(STM32U0xx) #define USB_IRQn USB_DRD_FS_IRQn #define USB_IRQHandler USB_DRD_FS_IRQHandler #elif defined(STM32U5xx) && !defined(USB_DRD_FS) diff --git a/libraries/USBDevice/src/usbd_conf_c5.c b/libraries/USBDevice/src/usbd_confv2.c similarity index 87% rename from libraries/USBDevice/src/usbd_conf_c5.c rename to libraries/USBDevice/src/usbd_confv2.c index 80f1931d46..b22750a4f0 100644 --- a/libraries/USBDevice/src/usbd_conf_c5.c +++ b/libraries/USBDevice/src/usbd_confv2.c @@ -1,11 +1,15 @@ /** ****************************************************************************** - * @file usbd_conf_c5.c - * @brief STM32C5 HAL v2 USB device low-level adapter. + * @file usbd_confv2.c + * @brief HAL v2 USB device low-level adapter. ****************************************************************************** */ -#if defined(USBCON) && defined(USE_HALV2_DRIVER) && defined(STM32C5xx) +#if defined(USBCON) && defined(USE_HALV2_DRIVER) + +#if !defined(STM32C5xx) +#warning "USB device support is currently implemented only for STM32C5xx HAL v2." +#else #include "usbd_core.h" #include "usbd_if.h" @@ -20,20 +24,19 @@ static USBD_HandleTypeDef *g_pdev; static uint8_t g_stalled_in; static uint8_t g_stalled_out; -static void USBD_C5_ErrorHandler(void) +static void USBD_V2_ErrorHandler(void) { Error_Handler(); } -static void USBD_C5_ConfigPinsAndIrq(void) +static void USBD_V2_ConfigPinsAndIrq(void) { - /* USB DRD FS owns PA11/PA12 and configures these fixed USB pins itself - * during peripheral initialization. Do not configure a GPIO alternate - * function here: C5 USB differs from the older USB device IPs. */ + /* The HAL v2 USB DRD FS PCD owns PA11/PA12 and configures these fixed USB + * pins during peripheral initialization. */ HAL_RCC_USB_EnableClock(); - HAL_CORTEX_NVIC_SetPriority(USB_DRD_FS_IRQn, USBD_IRQ_PRIO, USBD_IRQ_SUBPRIO); - HAL_CORTEX_NVIC_EnableIRQ(USB_DRD_FS_IRQn); + HAL_CORTEX_NVIC_SetPriority(USB_IRQn, USBD_IRQ_PRIO, USBD_IRQ_SUBPRIO); + HAL_CORTEX_NVIC_EnableIRQ(USB_IRQn); } void HAL_PCD_SetupStageCallback(hal_pcd_handle_t *hpcd) @@ -100,7 +103,7 @@ void HAL_PCD_DisconnectCallback(hal_pcd_handle_t *hpcd) USBD_LL_DevDisconnected(g_pdev); } -void USB_DRD_FS_IRQHandler(void) +void USB_IRQHandler(void) { HAL_PCD_IRQHandler(&g_hpcd); } @@ -119,7 +122,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) }; USBD_reenumerate(); - USBD_C5_ConfigPinsAndIrq(); + USBD_V2_ConfigPinsAndIrq(); g_pdev = pdev; g_stalled_in = 0U; @@ -127,16 +130,16 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) pdev->pData = &g_hpcd; if (HAL_PCD_Init(&g_hpcd, HAL_PCD_DRD_FS) != HAL_OK) { - USBD_C5_ErrorHandler(); + USBD_V2_ErrorHandler(); } if (HAL_PCD_SetConfig(&g_hpcd, &config) != HAL_OK) { - USBD_C5_ErrorHandler(); + USBD_V2_ErrorHandler(); } for (uint32_t i = 0U; i < (DEV_NUM_EP + 1U); i++) { if (HAL_PCD_PMAConfig(&g_hpcd, ep_def[i].ep_adress, ep_def[i].ep_kind, ep_def[i].ep_size) != HAL_OK) { - USBD_C5_ErrorHandler(); + USBD_V2_ErrorHandler(); } } @@ -146,7 +149,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { (void)pdev; - HAL_CORTEX_NVIC_DisableIRQ(USB_DRD_FS_IRQn); + HAL_CORTEX_NVIC_DisableIRQ(USB_IRQn); HAL_PCD_DeInit(&g_hpcd); HAL_RCC_USB_DisableClock(); g_pdev = NULL; @@ -248,4 +251,5 @@ void USBD_LL_Delay(uint32_t delay) HAL_Delay(delay); } -#endif /* USBCON && USE_HALV2_DRIVER && STM32C5xx */ +#endif /* STM32C5xx */ +#endif /* USBCON && USE_HALV2_DRIVER */ From 80f14e8e4ffdc021d1cce2b0b513d77e3e516e15 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Wed, 19 Aug 2026 14:08:05 +0800 Subject: [PATCH 15/17] fix(xiao): align board menus with core conventions --- boards.txt | 65 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/boards.txt b/boards.txt index 9698863bea..0d996e677a 100644 --- a/boards.txt +++ b/boards.txt @@ -2169,9 +2169,10 @@ GenC0.menu.upload_method.OpenOCDDapLink.debug.server.openocd.scripts.1={runtime. ################################################################################ # Seeed XIAO STM32C5 -XIAO_STM32C5.name=Seeed XIAO STM32C5 +XIAO_STM32C5.name=Seeed Studio XIAO_STM32C5.build.core=arduino +XIAO_STM32C5.build.family=SEEED_STUDIO XIAO_STM32C5.build.board=XIAO_STM32C5 XIAO_STM32C5.build.variant=STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U) XIAO_STM32C5.build.variant_h=variant_XIAO_STM32C5.h @@ -2196,11 +2197,65 @@ XIAO_STM32C5.debug.svd_file={runtime.tools.STM32_SVD.path}/svd/STM32C5xx/STM32C5 XIAO_STM32C5.vid.0=0x2886 XIAO_STM32C5.pid.0=0x80C5 -# USB CDC is the user-facing default. The temporary None option permits -# non-USB phase-1 validation until C5 HAL v2 USB support is implemented. -XIAO_STM32C5.menu.usb.CDC=CDC (Serial) -XIAO_STM32C5.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC +# Seeed XIAO STM32C5 +XIAO_STM32C5.menu.pnum.XIAO_STM32C5=Seeed XIAO STM32C5 +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.board=XIAO_STM32C5 +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.product_line=STM32C5A3xx +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.variant=STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U) +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.variant_h=variant_XIAO_STM32C5.h +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.ldscript=ldscript_XIAO_STM32C5.ld +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.upload.maximum_size=1015808 +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.upload.maximum_data_size=262144 +XIAO_STM32C5.menu.pnum.XIAO_STM32C5.debug.svd_file={runtime.tools.STM32_SVD.path}/svd/STM32C5xx/STM32C5A3.svd + +# U(S)ART support +XIAO_STM32C5.menu.xserial.generic=Enabled (generic 'Serial') +XIAO_STM32C5.menu.xserial.none=Enabled (no generic 'Serial') +XIAO_STM32C5.menu.xserial.none.build.xSerial=-DHAL_UART_MODULE_ENABLED -DHWSERIAL_NONE +XIAO_STM32C5.menu.xserial.disabled=Disabled (no Serial support) +XIAO_STM32C5.menu.xserial.disabled.build.xSerial= + +# USB connectivity XIAO_STM32C5.menu.usb.none=None +XIAO_STM32C5.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) +XIAO_STM32C5.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC +XIAO_STM32C5.menu.usb.CDC=CDC (no generic 'Serial') +XIAO_STM32C5.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB + +# Optimize +XIAO_STM32C5.menu.opt.osstd=Smallest (-Os default) +XIAO_STM32C5.menu.opt.oslto=Smallest (-Os) with LTO +XIAO_STM32C5.menu.opt.oslto.build.flags.optimize=-Os -flto +XIAO_STM32C5.menu.opt.o1std=Fast (-O1) +XIAO_STM32C5.menu.opt.o1std.build.flags.optimize=-O1 +XIAO_STM32C5.menu.opt.o1lto=Fast (-O1) with LTO +XIAO_STM32C5.menu.opt.o1lto.build.flags.optimize=-O1 -flto +XIAO_STM32C5.menu.opt.o2std=Faster (-O2) +XIAO_STM32C5.menu.opt.o2std.build.flags.optimize=-O2 +XIAO_STM32C5.menu.opt.o2lto=Faster (-O2) with LTO +XIAO_STM32C5.menu.opt.o2lto.build.flags.optimize=-O2 -flto +XIAO_STM32C5.menu.opt.o3std=Fastest (-O3) +XIAO_STM32C5.menu.opt.o3std.build.flags.optimize=-O3 +XIAO_STM32C5.menu.opt.o3lto=Fastest (-O3) with LTO +XIAO_STM32C5.menu.opt.o3lto.build.flags.optimize=-O3 -flto +XIAO_STM32C5.menu.opt.ogstd=Debug (-Og) +XIAO_STM32C5.menu.opt.ogstd.build.flags.optimize=-Og + +# Debug information +XIAO_STM32C5.menu.dbg.none=None +XIAO_STM32C5.menu.dbg.enable=Symbols Enabled (-g) +XIAO_STM32C5.menu.dbg.enable.build.flags.debug=-g + +# C Runtime Library +XIAO_STM32C5.menu.rtlib.nano=Newlib Nano (default) +XIAO_STM32C5.menu.rtlib.nanofp=Newlib Nano + Float Printf +XIAO_STM32C5.menu.rtlib.nanofp.build.flags.ldspecs=--specs=nano.specs -u _printf_float +XIAO_STM32C5.menu.rtlib.nanofs=Newlib Nano + Float Scanf +XIAO_STM32C5.menu.rtlib.nanofs.build.flags.ldspecs=--specs=nano.specs -u _scanf_float +XIAO_STM32C5.menu.rtlib.nanofps=Newlib Nano + Float Printf/Scanf +XIAO_STM32C5.menu.rtlib.nanofps.build.flags.ldspecs=--specs=nano.specs -u _printf_float -u _scanf_float +XIAO_STM32C5.menu.rtlib.full=Newlib Standard +XIAO_STM32C5.menu.rtlib.full.build.flags.ldspecs= ################################################################################ # Generic C5 From 4b38d5a323d4eeb2fc604708aca75361060759c8 Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Wed, 19 Aug 2026 14:08:05 +0800 Subject: [PATCH 16/17] fix(xiao): name SPI3 MOSI alternate function --- .../C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h index e00b051c78..51418af1f5 100644 --- a/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -32,6 +32,7 @@ /* Alternate functions used by the default board peripherals. */ #define PA9_ALT1 (PA9 | ALT1) #define PA10_ALT1 (PA10 | ALT1) +#define PB15_ALT2 (PB15 | ALT2) #define NUM_DIGITAL_PINS 21 #define NUM_ANALOG_INPUTS 4 @@ -46,7 +47,7 @@ #define PIN_SPI_SS1 NUM_DIGITAL_PINS #define PIN_SPI_SS2 NUM_DIGITAL_PINS #define PIN_SPI_SS3 NUM_DIGITAL_PINS -#define PIN_SPI_MOSI (PB15 | ALT2) +#define PIN_SPI_MOSI PB15_ALT2 #define PIN_SPI_MISO PB0 #define PIN_SPI_SCK PE2 From b9e53e9fb32299903d74716dc7c2bb02fe3c5b3a Mon Sep 17 00:00:00 2001 From: cumin <13809292481@163.com> Date: Wed, 19 Aug 2026 14:08:06 +0800 Subject: [PATCH 17/17] revert(spi): drop board-specific workarounds --- libraries/SPI/src/SPI.cpp | 6 ++-- libraries/SPI/src/SPI.h | 2 +- libraries/SPI/src/utility/spi_com.c | 47 +---------------------------- 3 files changed, 5 insertions(+), 50 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 7d328b8469..2a23c0ef31 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -13,9 +13,9 @@ SPIClass SPI; -void SPIClass::configSpi(const SPISettings &settings, bool force) +void SPIClass::configSpi(const SPISettings &settings) { - if (force || _spiSettings != settings) { + if (_spiSettings != settings) { _spiSettings = settings; uint32_t clock = settings.getClockFreq(); @@ -79,7 +79,7 @@ void SPIClass::begin(SPIBusMode busMode) SPI_MODE0, busMode ); - configSpi(defaultSettings, true); + configSpi(defaultSettings); } /** diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 279b27cad5..0560a0b7f0 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -135,7 +135,7 @@ class SPIClass : public HardwareSPI { /* Current SPISettings */ SPISettings _spiSettings = SPISettings(); - void configSpi(const SPISettings &settings, bool force = false); + void configSpi(const SPISettings &settings); }; extern SPIClass SPI; diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 52c6160843..1778e06d80 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -20,17 +20,6 @@ extern "C" { #endif -#if defined(USE_HALV2_DRIVER) -/* HAL v2 polling APIs use HAL_GetTick() for their timeout. On the current - * Arduino C5 clock path that tick is not guaranteed to advance while polling, - * so use the Arduino microsecond clock to bound LL polling instead. */ -static bool spi_transfer_timed_out(uint32_t start_us) -{ - return (SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) - && ((uint32_t)(micros() - start_us) >= (SPI_TRANSFER_TIMEOUT * 1000UL)); -} -#endif - /* Private Functions */ /** * @brief return clock freq of an SPI instance @@ -575,12 +564,6 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff { spi_status_e ret = SPI_OK; uint32_t tickstart, size = len; -#if defined(USE_HALV2_DRIVER) - uint32_t start_us; -#endif - if (obj == NULL || obj->spi == NP) { - return SPI_ERROR; - } SPI_TypeDef *_SPI = obj->spi; uint8_t *tx_buf = (uint8_t *)tx_buffer; @@ -588,9 +571,6 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff ret = SPI_ERROR; } else { tickstart = HAL_GetTick(); -#if defined(USE_HALV2_DRIVER) - start_us = micros(); -#endif #if defined(SPI_CR2_TSIZE) /* Start transfer */ @@ -601,32 +581,14 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff while (size--) { #if defined(SPI_SR_TXP) -#if defined(USE_HALV2_DRIVER) - while (!LL_SPI_IsActiveFlag_TXP(_SPI)) { - if (spi_transfer_timed_out(start_us)) { - ret = SPI_TIMEOUT; - goto spi_transfer_end; - } - } -#else while (!LL_SPI_IsActiveFlag_TXP(_SPI)); -#endif #else while (!LL_SPI_IsActiveFlag_TXE(_SPI)); #endif LL_SPI_TransmitData8(_SPI, tx_buf ? *tx_buf++ : 0XFF); #if defined(SPI_SR_RXP) -#if defined(USE_HALV2_DRIVER) - while (!LL_SPI_IsActiveFlag_RXP(_SPI)) { - if (spi_transfer_timed_out(start_us)) { - ret = SPI_TIMEOUT; - goto spi_transfer_end; - } - } -#else while (!LL_SPI_IsActiveFlag_RXP(_SPI)); -#endif #else while (!LL_SPI_IsActiveFlag_RXNE(_SPI)); #endif @@ -636,24 +598,17 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff LL_SPI_ReceiveData8(_SPI); } if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) && -#if defined(USE_HALV2_DRIVER) - (spi_transfer_timed_out(start_us))) { -#else (HAL_GetTick() - tickstart >= SPI_TRANSFER_TIMEOUT)) { -#endif ret = SPI_TIMEOUT; break; } } #if defined(SPI_IFCR_EOTC) -spi_transfer_end: // Add a delay before disabling SPI otherwise last-bit/last-clock may be truncated // See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294 // Computed delay is half SPI clock - if (ret == SPI_OK) { - delayMicroseconds(obj->disable_delay); - } + delayMicroseconds(obj->disable_delay); /* Close transfer */ /* Clear flags */