diff --git a/boards.txt b/boards.txt index 6c3dfcc648..0d996e677a 100644 --- a/boards.txt +++ b/boards.txt @@ -2167,6 +2167,96 @@ 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 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 +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 + +# 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 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..e83dcd55ab --- /dev/null +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.cpp @@ -0,0 +1,105 @@ +/* + * 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 + 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 + PB_13, // D14 / FDCAN2_TX + PB_14, // D15 / CAN_STB + 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 + PH_2 // BOOT0 / user button (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..ff40604f8b --- /dev/null +++ b/variants/STM32C5xx/C593C(E-G)(T-U)_C5A3CG(T-U)/variant_XIAO_STM32C5.h @@ -0,0 +1,99 @@ +/* + * 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 PE2 8 +#define PB0 9 +#define PB15 10 +#define PB8 11 +#define PB9 12 +#define PB5 13 +#define PB13 14 +#define PB14 15 + +/* 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 +#define PH2 21 // BOOT0 / user button + +/* 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 22 +#define NUM_ANALOG_INPUTS 4 + +#ifndef LED_BUILTIN + #define LED_BUILTIN PB12 +#endif + +// On-board user button. The physical button is active low and is also +// connected to the MCU BOOT0/PH2 pin. +#define B1_BTN PH2 +#ifndef USER_BTN + #define USER_BTN B1_BTN +#endif + +/* 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 PB15_ALT2 +#define PIN_SPI_MISO PB0 +#define PIN_SPI_SCK PE2 + +#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