Skip to content

Add XIAO ESP32-C5 board definition#393

Open
sigmdel wants to merge 1 commit intopioarduino:mainfrom
sigmdel:main
Open

Add XIAO ESP32-C5 board definition#393
sigmdel wants to merge 1 commit intopioarduino:mainfrom
sigmdel:main

Conversation

@sigmdel
Copy link

@sigmdel sigmdel commented Feb 18, 2026

Description:

Board definition for the Seeed Studio XIAO ESP32-C5.

Source : seeed-xiao-esp32-c5.json and Questions on the XIAO ESP32C5 board definition

Issue :
Related issue (if applicable): fixes #

Checklist:

  • The pull request is done against the latest develop branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR, more changes are allowed when changing boards.json
  • I accept the CLA

Summary by CodeRabbit

  • Chores
    • Added support for Seeed Studio XIAO ESP32C5 board with WiFi, Bluetooth, Zigbee, and Thread connectivity. Compatible with Arduino and ESPiDF frameworks.

@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

📝 Walkthrough

Walkthrough

A new PlatformIO board manifest file for Seeed Studio XIAO ESP32C5 is introduced, containing complete platform configuration including build settings, memory layout, connectivity options, debug configuration, supported frameworks, and upload specifications.

Changes

Cohort / File(s) Summary
Seeed XIAO ESP32C5 Board Manifest
seeed_xiao_esp32c5.json
New platform manifest defining build configuration (ESP32 core, MCU, variant, memory), connectivity support (WiFi, Bluetooth, Zigbee, Thread), debug tooling (OpenOCD), framework support (Arduino, ESP-IDF), and upload parameters for the Seeed XIAO ESP32C5 board.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A new board joins the warren so bright,
ESP32C5 takes its flight,
Configuration laid out with care,
Seeed's XIAO blooms everywhere! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a board definition for the XIAO ESP32-C5, which matches the single JSON file addition and PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@seeed_xiao_esp32c5.json`:
- Line 49: The "url" field currently points to the generic XIAO series wiki;
update the "url" value in seeed_xiao_esp32c5.json (the "url" key) to the
SeeedStudio XIAO ESP32-C5–specific getting-started/wiki page (the
PlatformIO/ESP32-C5 guide) so users are taken directly to the C5 board
documentation.
- Line 44: The maximum_ram_size value is set too low (327680) and causes false
"sketch too big" warnings; update the JSON entry for maximum_ram_size to reflect
the measured available internal RAM (e.g., change the value to 344064 to cover
~338 KB measured) so sketches between 320–338 KB no longer fail; locate the
"maximum_ram_size" key in the board manifest and replace its numeric value
accordingly (ensure any comments or documentation near the maximum_ram_size key
are updated to reflect the new chosen value).
- Around line 3-7: Remove the unused build.arduino.ldscript entry and move the
partitions and memory_type keys out of build.arduino into the top-level build
object (use keys "partitions" and "memory_type" under "build"), matching the
pattern used in seeed_xiao_esp32s3.json; ensure build.arduino no longer contains
ldscript and that build.partitions and build.memory_type are present at the flat
build.* level so the ESP-IDF and Arduino framework resolution work correctly.

Comment on lines +3 to +7
"arduino": {
"ldscript": "esp32c5_out.ld",
"partitions": "default_8MB.csv",
"memory_type": "qio_qspi"
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the linker script, partition table, and board variant exist in the Arduino ESP32 core.

echo "=== Linker script ==="
fd "esp32c5_out.ld" --type f

echo "=== Partition table ==="
fd "default_8MB.csv" --type f

echo "=== Variant directory ==="
fd "XIAO_ESP32C5" --type d

echo "=== Other ESP32-C5 board JSON files for comparison ==="
rg -l "esp32c5" --type json -g "*.json"

Repository: pioarduino/platform-espressif32

Length of output: 360


🏁 Script executed:

#!/bin/bash
# Check what the other ESP32-C5 boards reference

echo "=== Comparing ldscript references in ESP32-C5 boards ==="
for f in boards/esp32-c5-devkitc*.json seeed_xiao_esp32c5.json; do
  echo "--- $f ---"
  rg '"ldscript"' "$f" -A 0
done

echo ""
echo "=== Comparing partitions references in ESP32-C5 boards ==="
for f in boards/esp32-c5-devkitc*.json seeed_xiao_esp32c5.json; do
  echo "--- $f ---"
  rg '"partitions"' "$f" -A 0
done

echo ""
echo "=== All .ld files in repository ==="
fd "\.ld$" --type f

echo ""
echo "=== All .csv files in repository ==="
fd "\.csv$" --type f | head -20

Repository: pioarduino/platform-espressif32

Length of output: 1184


🏁 Script executed:

#!/bin/bash
# Understand how ldscript and partitions are resolved

echo "=== Search for ldscript handling in platform.py ==="
rg -i "ldscript" --type py | head -20

echo ""
echo "=== Search for partitions handling in platform.py ==="
rg -i "partitions" --type py | head -20

echo ""
echo "=== Check Arduino core directory structure ==="
fd "esp32" --type d -g "*arduino*" | head -10

echo ""
echo "=== Look for esp32c5 in builder files ==="
rg "esp32c5" --type py

Repository: pioarduino/platform-espressif32

Length of output: 2636


🏁 Script executed:

#!/bin/bash
# Find Arduino framework handling of ldscript

echo "=== Search Arduino framework builder for ldscript ==="
find builder -name "*.py" -type f | xargs grep -l "ldscript" 2>/dev/null

echo ""
echo "=== Content of Arduino framework builder if it exists ==="
ls -la builder/frameworks/ | grep -i arduino

echo ""
echo "=== Check espidf.py for Arduino ldscript handling ==="
rg "build\.ldscript|build\.arduino\.ldscript" --type py -B 2 -A 2

echo ""
echo "=== Check main.py for ldscript handling ==="
rg "ldscript" builder/main.py -B 2 -A 2

Repository: pioarduino/platform-espressif32

Length of output: 721


🏁 Script executed:

#!/bin/bash
# Examine Arduino framework builder

echo "=== First 100 lines of arduino.py ==="
head -100 builder/frameworks/arduino.py

echo ""
echo "=== Search for ldscript in arduino.py ==="
rg "ldscript" builder/frameworks/arduino.py -B 3 -A 3

echo ""
echo "=== Search for how Arduino gets core directory ==="
rg "FRAMEWORK_DIR|arduino.*core" builder/frameworks/arduino.py -B 2 -A 2 | head -40

Repository: pioarduino/platform-espressif32

Length of output: 4064


🏁 Script executed:

#!/bin/bash
# Check all board files for ldscript usage

echo "=== ESP32 boards that define ldscript ==="
rg '"ldscript"' boards/*.json --type json

echo ""
echo "=== Count: boards with ldscript vs without ==="
echo "Boards WITH ldscript:"
rg -l '"ldscript"' boards/*.json --type json | wc -l
echo "Total boards:"
ls boards/*.json | wc -l

echo ""
echo "=== Search for esp32c5_out.ld anywhere in repo ==="
rg "esp32c5_out" .

echo ""
echo "=== Check if this is from Seeed's reference definition ==="
# Look at git log to see where this came from
git log --oneline --all -S "esp32c5_out.ld" 2>/dev/null | head -5

Repository: pioarduino/platform-espressif32

Length of output: 161


🏁 Script executed:

#!/bin/bash
# Simpler check of board files

echo "=== ESP32 boards that define ldscript ==="
rg '"ldscript"' boards/*.json --type json 2>/dev/null | cut -d: -f1 | sort -u

echo ""
echo "=== Total boards with ldscript ==="
rg -l '"ldscript"' boards/*.json --type json 2>/dev/null | wc -l

echo ""
echo "=== Search for esp32c5_out in entire repo ==="
rg "esp32c5_out" . 2>/dev/null

echo ""
echo "=== Check the actual seeed_xiao_esp32c5.json file ==="
cat seeed_xiao_esp32c5.json | head -30

Repository: pioarduino/platform-espressif32

Length of output: 932


🏁 Script executed:

#!/bin/bash
# Check if Arduino framework builder uses build.arduino.ldscript

echo "=== Entire arduino.py file size and search for ldscript/variant ==="
wc -l builder/frameworks/arduino.py
echo ""
rg -i "build\.(arduino\.)?ldscript|build\.variant" builder/frameworks/arduino.py

echo ""
echo "=== Check how variants and ldscripts are used in espidf vs arduino ==="
echo "ESP-IDF framework:"
rg "build\.ldscript|build\.esp-idf\.ldscript" builder/frameworks/espidf.py -B 1 -A 1

echo ""
echo "=== Check if build.arduino.* is used anywhere in builders ==="
rg "build\.arduino\." builder/frameworks/ --type py

Repository: pioarduino/platform-espressif32

Length of output: 704


🏁 Script executed:

#!/bin/bash
# Check how other ESP32-C5 boards are configured

echo "=== Full content of a working ESP32-C5 devkit board for comparison ==="
cat boards/esp32-c5-devkitc-1.json

echo ""
echo "=== Check which frameworks use ldscript in espidf.py ==="
rg -B 5 "build\.ldscript" builder/frameworks/espidf.py | head -20

echo ""
echo "=== Verify: does Arduino framework even check for build.arduino.ldscript? ==="
rg "build\.arduino" builder/frameworks/arduino.py

Repository: pioarduino/platform-espressif32

Length of output: 1038


🏁 Script executed:

#!/bin/bash
# Verify Arduino framework actually uses ldscript and check variant

echo "=== Check entire arduino.py for any ldscript usage ==="
grep -i "ldscript" builder/frameworks/arduino.py

echo ""
echo "=== Check if XIAO_ESP32C5 variant or esp32c5 variant directory exists ==="
find . -type d -name "*XIAO*" 2>/dev/null
find . -type d -name "*esp32c5*" 2>/dev/null

echo ""
echo "=== Confirm: arduino.py only uses build.arduino.memory_type, NOT ldscript ==="
grep "build\.arduino\." builder/frameworks/arduino.py

echo ""
echo "=== For comparison, check how ESP-IDF framework handles ldscript ==="
head -1 boards/esp32-c5-devkitc-1.json | grep -c "frameworks.*espidf" || echo "Checking frameworks in devkit board..."
cat boards/esp32-c5-devkitc-1.json | grep -A 2 "frameworks"

Repository: pioarduino/platform-espressif32

Length of output: 440


🏁 Script executed:

#!/bin/bash
# Understand where partitions come from

echo "=== How espidf.py resolves partitions (the only framework that uses them) ==="
rg "partitions_csv|PARTITIONS_TABLE_CSV" builder/frameworks/espidf.py -B 2 -A 2

echo ""
echo "=== Confirm: does arduino.py use partitions at all? ==="
grep -i "partition" builder/frameworks/arduino.py

echo ""
echo "=== Check if default_8MB.csv is used by other boards successfully ==="
rg "default_8MB.csv" boards/*.json

Repository: pioarduino/platform-espressif32

Length of output: 3994


🏁 Script executed:

#!/bin/bash
# Check structure of boards that use partitions and memory_type

echo "=== A board using default_8MB.csv to see correct structure ==="
cat boards/seeed_xiao_esp32s3.json | head -40

echo ""
echo "=== Verify board.get() doesn't traverse nested keys ==="
grep -A 5 "board.get.*build\." builder/frameworks/espidf.py | head -20

Repository: pioarduino/platform-espressif32

Length of output: 1676


🏁 Script executed:

#!/bin/bash
# Check exact location where partitions and ldscript are accessed in espidf.py

echo "=== CRITICAL: Check exact build.* keys accessed in espidf.py ==="
rg "board\.get\(\"build\." builder/frameworks/espidf.py | head -30

echo ""
echo "=== Verify: does seeed_xiao_esp32s3.json work if partitions is nested under arduino? ==="
echo "Checking if espidf.py looks for build.arduino.partitions:"
rg "board\.get.*build\.arduino" builder/frameworks/espidf.py

echo ""
echo "=== Confirm where partitions is nested in seeed_xiao_esp32s3.json ==="
rg -A 6 '"arduino"' boards/seeed_xiao_esp32s3.json | grep -A 2 partitions
</parameter>

Repository: pioarduino/platform-espressif32

Length of output: 2046


🏁 Script executed:

#!/bin/bash
# Check nesting structure of partitions across boards

echo "=== How many boards have build.partitions (flat) vs build.arduino.partitions (nested)? ==="
echo "Flat structure (build.partitions):"
rg '"build".*{' boards/*.json -A 20 | rg '"partitions"' | grep -v arduino | wc -l

echo ""
echo "Nested under arduino (build.arduino.partitions):"
rg '"build".*{' boards/*.json -A 20 | rg -B 5 '"partitions"' | grep -B 5 arduino | wc -l

echo ""
echo "=== Show examples of FLAT structure (partitions NOT under arduino) ==="
for f in boards/*.json; do
  if grep -q '"partitions"' "$f" && ! (grep -B 3 '"partitions"' "$f" | grep -q "arduino"); then
    echo "=== $f ==="
    grep -B 3 -A 1 '"partitions"' "$f" | head -8
    break
  fi
done

echo ""
echo "=== Show examples of NESTED structure (partitions UNDER arduino) ==="
for f in boards/seeed*.json; do
  if grep -q '"partitions"' "$f"; then
    echo "=== $f ==="
    grep -B 3 -A 1 '"partitions"' "$f" | head -8
  fi
done

Repository: pioarduino/platform-espressif32

Length of output: 722


🏁 Script executed:

#!/bin/bash
# Simpler check of board structure

echo "=== Check seeed_xiao_esp32s3.json build section ==="
cat boards/seeed_xiao_esp32s3.json | grep -A 15 '"build"' | head -20

echo ""
echo "=== Check seeed_xiao_esp32c5.json build section ==="
cat seeed_xiao_esp32c5.json | grep -A 15 '"build"' | head -20

echo ""
echo "=== How espidf.py accesses partitions ==="
grep "partitions_csv.*board.get" builder/frameworks/espidf.py

echo ""
echo "=== Verify: espidf.py looks for build.partitions (NOT build.arduino.partitions) ==="
grep -A 2 'partitions_csv = board.get' builder/frameworks/espidf.py

Repository: pioarduino/platform-espressif32

Length of output: 1346


🏁 Script executed:

#!/bin/bash
# Check if both boards have espidf framework and if PlatformIO handles nested keys

echo "=== Does seeed_xiao_esp32s3.json use espidf framework? ==="
grep -A 20 '"frameworks"' boards/seeed_xiao_esp32s3.json

echo ""
echo "=== Does seeed_xiao_esp32c5.json use espidf framework? ==="
grep -A 20 '"frameworks"' seeed_xiao_esp32c5.json

echo ""
echo "=== Check if PlatformIO board.get() handles nested keys ==="
# PlatformIO uses dot notation for nested access, let me check
grep -r "\.get\(" builder/frameworks/espidf.py | grep build | head -5

echo ""
echo "=== Check if there are any boards with FLAT partitions structure ==="
find boards -name "*.json" -exec grep -l '"partitions"' {} \; | head -3 | xargs -I {} sh -c 'echo "=== {} ==="; grep -B 5 "partitions" {} | tail -7'

Repository: pioarduino/platform-espressif32

Length of output: 5125


Move partition table and memory_type definitions to build. (flat) structure; remove unused ldscript.*

The ldscript key under build.arduino is unused by the Arduino framework builder and will cause ESP-IDF builds to fail—this is the only board in the repository that defines it, and no other board needs it. Move partitions and memory_type to the flat build.* level (not nested under build.arduino) to match both the expected framework resolution paths and the configuration pattern used by seeed_xiao_esp32s3.json:

Suggested structure
"build": {
    "partitions": "default_8MB.csv",
    "memory_type": "qio_qspi",
    "core": "esp32",
    ...
}

Remove the build.arduino.ldscript key entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@seeed_xiao_esp32c5.json` around lines 3 - 7, Remove the unused
build.arduino.ldscript entry and move the partitions and memory_type keys out of
build.arduino into the top-level build object (use keys "partitions" and
"memory_type" under "build"), matching the pattern used in
seeed_xiao_esp32s3.json; ensure build.arduino no longer contains ldscript and
that build.partitions and build.memory_type are present at the flat build.*
level so the ESP-IDF and Arduino framework resolution work correctly.

"require_upload_port": true,
"speed": 460800
},
"url": "https://wiki.seeedstudio.com/SeeedStudio_XIAO_Series_Introduction/",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

URL points to the generic XIAO series page instead of the XIAO ESP32-C5–specific wiki.

The board's URL should link directly to the C5 getting-started guide for PlatformIO users who follow it from the IDE.

💡 Suggested correction
-  "url": "https://wiki.seeedstudio.com/SeeedStudio_XIAO_Series_Introduction/",
+  "url": "https://wiki.seeedstudio.com/xiao_esp32c5_getting_started/",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"url": "https://wiki.seeedstudio.com/SeeedStudio_XIAO_Series_Introduction/",
"url": "https://wiki.seeedstudio.com/xiao_esp32c5_getting_started/",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@seeed_xiao_esp32c5.json` at line 49, The "url" field currently points to the
generic XIAO series wiki; update the "url" value in seeed_xiao_esp32c5.json (the
"url" key) to the SeeedStudio XIAO ESP32-C5–specific getting-started/wiki page
(the PlatformIO/ESP32-C5 guide) so users are taken directly to the C5 board
documentation.

"extra_flags": [
"-DARDUINO_XIAO_ESP32C5",
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=1",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you set USB_MODE to the fixed value 1 in the board manifest?
You should leave this up to the user in the platformio.ini file.
This requires the user to disable it in the platformio.ini file (build_unflags = -DUSB_MODE) in order to set USB_MODE to 0, which is not a good user experience.
Suggestion: Omit this line and allow the user to set this setting to 0 or 1 in platformio.ini.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sivar2311 Is correct the board has only the CDC/JTAG port.

@Jason2866
Copy link

Please fix the mentioned points and close this PR and open it against branch develop

@Jason2866
Copy link

Btw. Seedstudio has no clue about doing correct boards.json. Furthermore there fork of pioarduino (no where mentioned the source, violating license) is outdated and badly done.

@sigmdel
Copy link
Author

sigmdel commented Feb 19, 2026

Thank you for your comments, but I am a bit confused which is not a rare condition I'll concede.

When "-DARDUINO_USB_MODE=1", is removed from the json file, the following error obtains:

Compiling .pio/build/seeed_xiao_esp32c5/FrameworkArduino/USBMSC.cpp.o
In file included from /home/michel/.platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h:202,
                 from pin_names/main.cpp:5:
pin_names/main.cpp: In function 'void iopins()':
/home/michel/.platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.h:435:16: error: 'USBSerial' was not declared in this scope; did you mean 'Serial'?
  435 | #define Serial USBSerial
      |                ^~~~~~~~~
pin_names/main.cpp:37:3: note: in expansion of macro 'Serial'
   37 |   Serial.println("\n\nXIAO ESP32C5 I/O Pin Names and Numbers");
      |   ^~~~~~
Compiling .pio/build/seeed_xiao_esp32c5/FrameworkArduino/WMath.cpp.o
pin_names/main.cpp: In function 'void setup()':
/home/michel/.platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.h:435:16: error: 'USBSerial' was not declared in this scope; did you mean 'Serial'?
  435 | #define Serial USBSerial
      |                ^~~~~~~~~
pin_names/main.cpp:137:3: note: in expansion of macro 'Serial'
  137 |   Serial.begin();
      |   ^~~~~~
Compiling .pio/build/seeed_xiao_esp32c5/FrameworkArduino/WString.cpp.o
*** [.pio/build/seeed_xiao_esp32c5/src/main.cpp.o] Error 1
Compiling .pio/build/seeed_xiao_esp32c5/FrameworkArduino/base64.cpp.o

If "-DARDUINO_USB_MODE", is inserted in extra_flags, the project compiles and the following bit of code

  Serial.println("\nNative USB support")
  #ifdef ARDUINO_USB_MODE
  Serial. printf("  ARDUINO_USB_MODE is defined and equal to %d\n", ARDUINO_USB_MODE);
  #else
  Serial.println("  ARDUINO_USB_MODE is not defined");
  #endif

displays the following

Native USB support
 ARDUINO_USB_MODE is defined and equal to 1

Perhaps that's why "-DARDUINO_USB_MODE=1" is found in many json definitions files such as the XIAO ESP32C3, the the XIAO C6, the adafruit_qtpy_esp32c3.json etc which I think all have just a CDC/JTAG.

In any case, what would you advise?

@sivar2311
Copy link

The ESP32-C3 is limited to USB_MODE=1. Where as the C6 supports both 0 and 1.
I assumed the C5 does also support 0 and 1. I have to admit that I did not verified this yet. I'll take a closer look into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments