Skip to content

Commit 8c67df5

Browse files
committed
feat(xiao): add Seeed XIAO STM32C5 board support
1 parent 8bc8cc9 commit 8c67df5

4 files changed

Lines changed: 462 additions & 0 deletions

File tree

‎boards.txt‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,6 +2482,99 @@ GenC0.menu.upload_method.OpenOCDDapLink.upload.tool=openocd_upload
24822482
GenC0.menu.upload_method.OpenOCDDapLink.debug.server.openocd.scripts.0=interface/cmsis-dap.cfg
24832483
GenC0.menu.upload_method.OpenOCDDapLink.debug.server.openocd.scripts.1={runtime.platform.path}/debugger/select_swd.cfg
24842484

2485+
################################################################################
2486+
# Seeed XIAO STM32C5
2487+
# Docs: url=https://www.seeedstudio.com/
2488+
XIAO_STM32C5.name=Seeed Studio
2489+
2490+
XIAO_STM32C5.build.core=arduino
2491+
XIAO_STM32C5.build.family=SEEED_STUDIO
2492+
XIAO_STM32C5.build.board=XIAO_STM32C5
2493+
XIAO_STM32C5.build.variant=STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)
2494+
XIAO_STM32C5.build.variant_h=variant_XIAO_STM32C5.h
2495+
XIAO_STM32C5.build.ldscript=ldscript_XIAO_STM32C5.ld
2496+
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}
2497+
XIAO_STM32C5.build.mcu=cortex-m33
2498+
XIAO_STM32C5.build.fpu=-mfpu=fpv5-sp-d16
2499+
XIAO_STM32C5.build.float-abi=-mfloat-abi=hard
2500+
XIAO_STM32C5.build.series=STM32C5xx
2501+
XIAO_STM32C5.build.product_line=STM32C5A3xx
2502+
XIAO_STM32C5.build.hal=-DUSE_HALV2_DRIVER
2503+
XIAO_STM32C5.build.flash_offset=0x8000
2504+
XIAO_STM32C5.upload.maximum_size=1015808
2505+
XIAO_STM32C5.upload.maximum_data_size=262144
2506+
XIAO_STM32C5.upload.tool=uf2upload
2507+
XIAO_STM32C5.upload.protocol=serial
2508+
XIAO_STM32C5.upload.uf2.volume=XIAOC5BOOT
2509+
XIAO_STM32C5.upload.uf2.address=0x08008000
2510+
XIAO_STM32C5.upload.uf2.family=0x00C5C5C5
2511+
XIAO_STM32C5.upload.uf2.timeout=10000
2512+
XIAO_STM32C5.debug.svd_file={runtime.tools.STM32_SVD.path}/svd/STM32C5xx/STM32C5A3.svd
2513+
XIAO_STM32C5.vid.0=0x2886
2514+
XIAO_STM32C5.pid.0=0x80C5
2515+
2516+
# Seeed XIAO STM32C5
2517+
# Docs: url=https://www.seeedstudio.com/XIAO-STM32C5-p-7011.html
2518+
# Docs: mcu=STM32C5A3CG
2519+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5=Seeed XIAO STM32C5
2520+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.board=XIAO_STM32C5
2521+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.product_line=STM32C5A3xx
2522+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.variant=STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)
2523+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.variant_h=variant_XIAO_STM32C5.h
2524+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.build.ldscript=ldscript_XIAO_STM32C5.ld
2525+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.upload.maximum_size=1015808
2526+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.upload.maximum_data_size=262144
2527+
XIAO_STM32C5.menu.pnum.XIAO_STM32C5.debug.svd_file={runtime.tools.STM32_SVD.path}/svd/STM32C5xx/STM32C5A3.svd
2528+
2529+
# U(S)ART support
2530+
XIAO_STM32C5.menu.xserial.generic=Enabled (generic 'Serial')
2531+
XIAO_STM32C5.menu.xserial.none=Enabled (no generic 'Serial')
2532+
XIAO_STM32C5.menu.xserial.none.build.xSerial=-DHAL_UART_MODULE_ENABLED -DHWSERIAL_NONE
2533+
XIAO_STM32C5.menu.xserial.disabled=Disabled (no Serial support)
2534+
XIAO_STM32C5.menu.xserial.disabled.build.xSerial=
2535+
2536+
# USB connectivity
2537+
XIAO_STM32C5.menu.usb.none=None
2538+
XIAO_STM32C5.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART)
2539+
XIAO_STM32C5.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC
2540+
XIAO_STM32C5.menu.usb.CDC=CDC (no generic 'Serial')
2541+
XIAO_STM32C5.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB
2542+
2543+
# Optimize
2544+
XIAO_STM32C5.menu.opt.osstd=Smallest (-Os default)
2545+
XIAO_STM32C5.menu.opt.oslto=Smallest (-Os) with LTO
2546+
XIAO_STM32C5.menu.opt.oslto.build.flags.optimize=-Os -flto
2547+
XIAO_STM32C5.menu.opt.o1std=Fast (-O1)
2548+
XIAO_STM32C5.menu.opt.o1std.build.flags.optimize=-O1
2549+
XIAO_STM32C5.menu.opt.o1lto=Fast (-O1) with LTO
2550+
XIAO_STM32C5.menu.opt.o1lto.build.flags.optimize=-O1 -flto
2551+
XIAO_STM32C5.menu.opt.o2std=Faster (-O2)
2552+
XIAO_STM32C5.menu.opt.o2std.build.flags.optimize=-O2
2553+
XIAO_STM32C5.menu.opt.o2lto=Faster (-O2) with LTO
2554+
XIAO_STM32C5.menu.opt.o2lto.build.flags.optimize=-O2 -flto
2555+
XIAO_STM32C5.menu.opt.o3std=Fastest (-O3)
2556+
XIAO_STM32C5.menu.opt.o3std.build.flags.optimize=-O3
2557+
XIAO_STM32C5.menu.opt.o3lto=Fastest (-O3) with LTO
2558+
XIAO_STM32C5.menu.opt.o3lto.build.flags.optimize=-O3 -flto
2559+
XIAO_STM32C5.menu.opt.ogstd=Debug (-Og)
2560+
XIAO_STM32C5.menu.opt.ogstd.build.flags.optimize=-Og
2561+
2562+
# Debug information
2563+
XIAO_STM32C5.menu.dbg.none=None
2564+
XIAO_STM32C5.menu.dbg.enable=Symbols Enabled (-g)
2565+
XIAO_STM32C5.menu.dbg.enable.build.flags.debug=-g
2566+
2567+
# C Runtime Library
2568+
XIAO_STM32C5.menu.rtlib.nano=Newlib Nano (default)
2569+
XIAO_STM32C5.menu.rtlib.nanofp=Newlib Nano + Float Printf
2570+
XIAO_STM32C5.menu.rtlib.nanofp.build.flags.ldspecs=--specs=nano.specs -u _printf_float
2571+
XIAO_STM32C5.menu.rtlib.nanofs=Newlib Nano + Float Scanf
2572+
XIAO_STM32C5.menu.rtlib.nanofs.build.flags.ldspecs=--specs=nano.specs -u _scanf_float
2573+
XIAO_STM32C5.menu.rtlib.nanofps=Newlib Nano + Float Printf/Scanf
2574+
XIAO_STM32C5.menu.rtlib.nanofps.build.flags.ldspecs=--specs=nano.specs -u _printf_float -u _scanf_float
2575+
XIAO_STM32C5.menu.rtlib.full=Newlib Standard
2576+
XIAO_STM32C5.menu.rtlib.full.build.flags.ldspecs=
2577+
24852578
################################################################################
24862579
# Generic C5
24872580
GenC5.name=Generic STM32C5 series
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright (c) 2026, Seeed Technology Co., Ltd.
3+
* SPDX-License-Identifier: BSD-3-Clause
4+
*
5+
* The application starts after the 32 KiB TinyUF2 bootloader. Memory sizes are
6+
* supplied by boards.txt through LD_MAX_SIZE and LD_MAX_DATA_SIZE.
7+
*/
8+
ENTRY(Reset_Handler)
9+
10+
HEAP_SIZE = 0x2000;
11+
STACK_SIZE = 0x2000;
12+
13+
MEMORY
14+
{
15+
ROM (rx) : org = 0x08000000 + LD_FLASH_OFFSET, len = LD_MAX_SIZE - LD_FLASH_OFFSET
16+
/* TinyUF2 uses the final SRAM word for the 1200-bps reset handoff. */
17+
RAM (xrw) : org = 0x20000000, len = LD_MAX_DATA_SIZE - 4
18+
}
19+
20+
SECTIONS
21+
{
22+
.vectors :
23+
{
24+
. = ALIGN(8);
25+
KEEP(*(.vectors));
26+
. = ALIGN(8);
27+
} > ROM
28+
29+
.text :
30+
{
31+
. = ALIGN(8);
32+
*(.text);
33+
*(.text*);
34+
*(.glue_7);
35+
*(.glue_7t);
36+
*(.eh_frame);
37+
KEEP(*(.init));
38+
KEEP(*(.fini));
39+
. = ALIGN(8);
40+
_etext = .;
41+
} > ROM
42+
43+
.rodata :
44+
{
45+
. = ALIGN(8);
46+
*(.rodata);
47+
*(.rodata*);
48+
. = ALIGN(8);
49+
} > ROM
50+
51+
.ARM.extab (READONLY) :
52+
{
53+
. = ALIGN(8);
54+
*(.ARM.extab* .gnu.linkonce.armextab.*)
55+
. = ALIGN(8);
56+
} > ROM
57+
58+
.ARM (READONLY) :
59+
{
60+
. = ALIGN(8);
61+
__exidx_start = .;
62+
*(.ARM.exidx*);
63+
__exidx_end = .;
64+
. = ALIGN(8);
65+
} > ROM
66+
67+
.preinit_array (READONLY) :
68+
{
69+
. = ALIGN(8);
70+
PROVIDE_HIDDEN(__preinit_array_start = .);
71+
KEEP(*(.preinit_array*));
72+
PROVIDE_HIDDEN(__preinit_array_end = .);
73+
. = ALIGN(8);
74+
} > ROM
75+
76+
.init_array (READONLY) :
77+
{
78+
. = ALIGN(8);
79+
PROVIDE_HIDDEN(__init_array_start = .);
80+
KEEP(*(SORT(.init_array.*)));
81+
KEEP(*(.init_array*));
82+
PROVIDE_HIDDEN(__init_array_end = .);
83+
. = ALIGN(8);
84+
} > ROM
85+
86+
.fini_array (READONLY) :
87+
{
88+
. = ALIGN(8);
89+
PROVIDE_HIDDEN(__fini_array_start = .);
90+
KEEP(*(SORT(.fini_array.*)));
91+
KEEP(*(.fini_array*));
92+
PROVIDE_HIDDEN(__fini_array_end = .);
93+
. = ALIGN(8);
94+
} > ROM
95+
96+
.copy.table (READONLY) :
97+
{
98+
. = ALIGN(8);
99+
__copy_table_start__ = .;
100+
LONG(LOADADDR(.data));
101+
LONG(ADDR(.data));
102+
LONG(SIZEOF(.data) / 4);
103+
__copy_table_end__ = .;
104+
} > ROM
105+
106+
.zero.table (READONLY) :
107+
{
108+
. = ALIGN(8);
109+
__zero_table_start__ = .;
110+
LONG(ADDR(.bss));
111+
LONG(SIZEOF(.bss) / 4);
112+
__zero_table_end__ = .;
113+
} > ROM
114+
115+
.data :
116+
{
117+
. = ALIGN(8);
118+
_sidata = LOADADDR(.data);
119+
__data_start__ = .;
120+
_sdata = .;
121+
*(.data);
122+
*(.data*);
123+
. = ALIGN(8);
124+
_edata = .;
125+
} > RAM AT> ROM
126+
127+
.bss :
128+
{
129+
. = ALIGN(8);
130+
_sbss = .;
131+
__bss_start__ = _sbss;
132+
*(.bss);
133+
*(.bss*);
134+
*(COMMON);
135+
. = ALIGN(8);
136+
_ebss = .;
137+
__bss_end__ = _ebss;
138+
} > RAM
139+
140+
.heap (NOLOAD) :
141+
{
142+
. = ALIGN(8);
143+
__end__ = .;
144+
PROVIDE(end = .);
145+
_heap_start = .;
146+
. += HEAP_SIZE;
147+
. = ALIGN(8);
148+
_heap_end = .;
149+
__HeapLimit = .;
150+
} > RAM
151+
152+
.stack (NOLOAD) :
153+
{
154+
. = ALIGN(8);
155+
__StackLimit = .;
156+
. += STACK_SIZE;
157+
. = ALIGN(8);
158+
__StackTop = .;
159+
_estack = .;
160+
__stack = .;
161+
} > RAM
162+
163+
/DISCARD/ :
164+
{
165+
libc.a(*);
166+
libm.a(*);
167+
libgcc.a(*);
168+
}
169+
170+
.ARM.attributes 0 :
171+
{
172+
*(.ARM.attributes)
173+
}
174+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2026, Seeed Technology Co., Ltd.
3+
* SPDX-License-Identifier: BSD-3-Clause
4+
*/
5+
#if defined(ARDUINO_XIAO_STM32C5)
6+
7+
#include "pins_arduino.h"
8+
9+
const PinName digitalPin[] = {
10+
PA_0, // D0 / A0
11+
PA_1, // D1 / A1
12+
PA_2, // D2 / A2
13+
PA_3, // D3 / A3
14+
PB_7, // D4 / I2C1_SDA
15+
PB_6, // D5 / I2C1_SCL
16+
PA_9, // D6 / USART1_TX
17+
PA_10, // D7 / USART1_RX
18+
PE_2, // D8 / SPI3_SCK
19+
PB_0, // D9 / SPI3_MISO
20+
PB_15, // D10 / SPI3_MOSI
21+
PB_8, // D11 / FDCAN1_RX
22+
PB_9, // D12 / FDCAN1_TX
23+
PB_5, // D13 / FDCAN2_RX
24+
PB_13, // D14 / FDCAN2_TX
25+
PB_14, // D15 / CAN_STB
26+
PB_12, // Board LED, active low
27+
PB_3, // Onboard IMU / I2C2_SCL
28+
PB_4, // Onboard IMU / I2C2_SDA
29+
PC_13, // Onboard IMU / INT1
30+
PA_8 // Onboard IMU heater / TIM1_CH1
31+
};
32+
33+
const pin_size_t analogInputPin[] = {
34+
D0,
35+
D1,
36+
D2,
37+
D3
38+
};
39+
40+
/* TinyUF2 C5 (d52adcf) reserves the last SRAM word for the double-tap
41+
* handoff. The matching application linker script excludes this word from
42+
* the stack/heap RAM region. */
43+
static constexpr uintptr_t TINYUF2_HANDOFF_ADDRESS = 0x2003FFFCUL;
44+
static constexpr uint32_t TINYUF2_ENTER_DFU_MAGIC = 0xF01669EFUL;
45+
46+
extern "C" void CDC_LineCodingChanged(uint32_t bitrate)
47+
{
48+
if (bitrate == 1200U) {
49+
*reinterpret_cast<volatile uint32_t *>(TINYUF2_HANDOFF_ADDRESS) = TINYUF2_ENTER_DFU_MAGIC;
50+
__DSB();
51+
__ISB();
52+
NVIC_SystemReset();
53+
while (true) {
54+
}
55+
}
56+
}
57+
58+
extern "C" void SystemClock_Config(void)
59+
{
60+
if (HAL_RCC_HSE_Enable(HAL_RCC_HSE_ON) != HAL_OK) {
61+
Error_Handler();
62+
}
63+
64+
hal_rcc_psi_config_t psi_config;
65+
psi_config.psi_source = HAL_RCC_PSI_SRC_HSE;
66+
psi_config.psi_ref = HAL_RCC_PSI_REF_48MHZ;
67+
psi_config.psi_out = HAL_RCC_PSI_OUT_144MHZ;
68+
if (HAL_RCC_PSI_SetConfig(&psi_config) != HAL_OK) {
69+
Error_Handler();
70+
}
71+
if (HAL_RCC_PSIS_Enable() != HAL_OK) {
72+
Error_Handler();
73+
}
74+
75+
hal_rcc_bus_clk_config_t bus_config;
76+
bus_config.hclk_prescaler = HAL_RCC_HCLK_PRESCALER1;
77+
bus_config.pclk1_prescaler = HAL_RCC_PCLK_PRESCALER2;
78+
bus_config.pclk2_prescaler = HAL_RCC_PCLK_PRESCALER2;
79+
bus_config.pclk3_prescaler = HAL_RCC_PCLK_PRESCALER2;
80+
if (HAL_RCC_SetBusClockConfig(&bus_config) != HAL_OK) {
81+
Error_Handler();
82+
}
83+
84+
HAL_FLASH_ITF_SetLatency(HAL_FLASH, HAL_FLASH_ITF_LATENCY_4);
85+
if (HAL_RCC_SetSYSCLKSource(HAL_RCC_SYSCLK_SRC_PSIS) != HAL_OK) {
86+
Error_Handler();
87+
}
88+
HAL_FLASH_ITF_SetProgrammingDelay(HAL_FLASH, HAL_FLASH_ITF_PROGRAM_DELAY_2);
89+
if (HAL_RCC_CK48_SetKernelClkSource(HAL_RCC_CK48_CLK_SRC_HSE) != HAL_OK) {
90+
Error_Handler();
91+
}
92+
if (HAL_UpdateCoreClock() != HAL_OK) {
93+
Error_Handler();
94+
}
95+
}
96+
97+
void initVariant(void)
98+
{
99+
/* CAN_STB is active high. Keep the onboard transceiver out of standby. */
100+
pinMode(D15, OUTPUT);
101+
digitalWrite(D15, LOW);
102+
}
103+
104+
#endif /* ARDUINO_XIAO_STM32C5 */

0 commit comments

Comments
 (0)