Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitlab/ci/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ build_application_edge_agent:
EXAMPLE_TARGET: esp32s3
EXAMPLE_BOARD_BRAND: "lceda-course-examples"

- IMAGE: ["espressif/idf:release-v5.5"]
EXAMPLE_BOARD: ["xiao_esp32s3_sense"]
EXAMPLE_TARGET: esp32s3
EXAMPLE_BOARD_BRAND: "seeedstudio"

build_application_mcp_server_point:
extends:
- .build_examples_template
Expand Down
108 changes: 108 additions & 0 deletions application/edge_agent/boards/seeedstudio/xiao_esp32s3_sense/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Seeed Studio XIAO ESP32-S3 Sense

## Hardware Overview

| Feature | Specification |
|---------------|-----------------------------------------------------|
| Chip | ESP32-S3 (R8 module: 8 MB flash + 8 MB OPI PSRAM) |
| Flash | 8 MB QIO @ 80 MHz |
| PSRAM | Octal 80 MHz (wired to the OPI peripheral, no GPIO) |
| Camera | OV2640 over DVP 8-bit (XCLK 20 MHz, SCCB on GPIO39/40) |
| Microphone | On-board PDM mic on I2S0 (CLK=GPIO42, DATA=GPIO41) |
| microSD | On-board slot, SPI mode (CS=GPIO21, SCK=7, MISO=8, MOSI=9) |
| User LED | GPIO21 — **shared with SD card CS, see Notes** |
| Console | USB Serial/JTAG (internal USB PHY, on-board USB-C) |

Upstream board page: [XIAO ESP32-S3 Sense](https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/)

## GPIO Mapping

| Function | GPIO | Notes |
|---------------------------|------|-----------------------------------------|
| I2C SDA (camera SCCB) | 40 | Shared with header D4 |
| I2C SCL (camera SCCB) | 39 | Shared with header D5 / MTCK |
| I2S PDM CLK (mic) | 42 | Shared with D11 / MTMS |
| I2S PDM DATA (mic) | 41 | Shared with D12 / MTDI |
| SPI SCK (SD) | 7 | Shared with header D8 |
| SPI MISO (SD) | 8 | Shared with header D9 |
| SPI MOSI (SD) | 9 | Shared with header D10 |
| SPI CS (SD) | 21 | **Shared with user LED** |
| Camera XCLK | 10 | 20 MHz, generated by LEDC |
| Camera PCLK | 13 | |
| Camera VSYNC | 38 | |
| Camera HREF/DE | 47 | |
| Camera D0..D7 | 15, 17, 18, 16, 14, 12, 11, 48 | Y2..Y9 mapping |

Pin table source: [Sense MicroSD card wiki](https://wiki.seeedstudio.com/xiao_esp32s3_sense_filesystem/) and the Seeed Arduino `SD_Test` example (`SD.begin(21)`).

## Important Notes

### User LED and SD card share GPIO21

The XIAO ESP32-S3 Sense expansion board hardwires the SD card's CS line and the
on-board user LED to the same GPIO. They cannot be used at the same time. This
adaptation gives the SD card the pin (it is required for non-volatile storage of
sessions, memory, and router rules). If you need the LED instead, cut the J3
solder jumper on the expansion board to disconnect the SD card slot, then drop
a `status_led` device into `board_devices.yaml` that points at GPIO21 with
`active_level: 0` (the LED is active-low).

### JTAG over GPIO is unavailable

GPIO39–42 carry camera SCCB (39/40) and the PDM microphone (41/42). The XIAO
does not break out JTAG pins, so the firmware console is forced to the
on-board USB-C via `CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y`. GPIO JTAG debugging
is not possible on this board.

### SD card limits

The Seeed wiki states maximum 32 GB and FAT32 only. SDXC cards (≥ 64 GB,
exFAT) will not be mounted even after reformatting. Use cards from 4 GB to
32 GB, class A1 or better, formatted with the
[official SD Card Formatter](https://www.sdcard.org/downloads/formatter/) —
Windows "quick format" alone is not sufficient for cards that previously
held a Linux filesystem.

### Camera XCLK may affect SD reliability

GPIO10 emits a 20 MHz XCLK for the OV2640 while the camera is open. On some
units this couples into the SD card's SPI lines and produces CRC errors
(`sdmmc_card_init failed (0x107)`) when both are active. If you see this
under load, either close the camera when reading the SD card or drop the
SD SPI `frequency` in `board_devices.yaml` to `1000000` (1 MHz).

## Build & Flash

```bash
cd application/edge_agent

# Generate board-manager glue. Always rerun this after editing the YAML
# files under this directory, otherwise the stale generated C code under
# components/gen_bmgr_codes/ is compiled instead.
idf.py bmgr -c ./boards -b xiao_esp32s3_sense

# Build and flash
idf.py build
idf.py -p /dev/ttyACM0 flash monitor # Windows: -p COM3
```

The XIAO ESP32-S3 enters download mode automatically on most hosts; if the
flash hangs at "Connecting...", hold **BOOT**, tap **RESET**, release
**BOOT**, then retry.

## Partition Table

Uses `partitions_8MB.csv` (auto-selected from `CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y`
by `tools/cmake/flash_partition_defaults.cmake`). The 8 MB layout reserves a
read-only system FAT image and a writable data FAT image; the data root is
mounted on the SD card when present and falls back to the on-flash FAT
partition otherwise.

## Files

| File | Description |
|-------------------------------|----------------------------------------------------------|
| `board_info.yaml` | Board identity (chip, manufacturer, description) |
| `board_peripherals.yaml` | I2C0, I2S0 (PDM), SPI2 pin and bus configuration |
| `board_devices.yaml` | Camera, audio_adc, fs_sdcard device list |
| `sdkconfig.defaults.board` | Flash/PSRAM/console defaults + OV2640 + audio Kconfig |
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
version: 1.0.0
# Devices Configuration for Seeed Studio XIAO ESP32-S3 Sense
#
# Device summary:
# camera - OV2640 over DVP 8-bit (XCLK 20 MHz, JPEG 800x600@30FPS default)
# audio_adc - on-board PDM microphone (bare PDM, no codec IC)
# fs_sdcard - on-board microSD slot over SPI; mounts as CLAW_PATH_DATA root
#
# NOTE: the on-board user LED on GPIO21 is NOT exposed as a device here.
# The Sense expansion board hardwires the SD card's CS line to GPIO21, so
# the LED and the SD card physically cannot be used at the same time. SD
# storage is more useful for an edge-agent workload, so the LED is dropped.
# (See https://wiki.seeedstudio.com/xiao_esp32s3_sense_filesystem/ for the
# official pin table: CS = GPIO21, SCK = GPIO7, MISO = GPIO8, MOSI = GPIO9.)

devices:
- name: camera
type: camera
sub_type: dvp
version: default
config:
dvp_config:
reset_io: -1
pwdn_io: -1
vsync_io: 38
de_io: 47
pclk_io: 13
xclk_io: 10
xclk_freq: 20000000
data_width: CAM_CTLR_DATA_WIDTH_8
data_io:
data_io_0: 15
data_io_1: 17
data_io_2: 18
data_io_3: 16
data_io_4: 14
data_io_5: 12
data_io_6: 11
data_io_7: 48
peripherals:
- name: i2c_master
frequency: 100000

- name: audio_adc
chip: internal
type: audio_codec
version: default
config:
adc_enabled: true
dac_enabled: false
adc_max_channel: 1
adc_channel_mask: "1"
adc_init_gain: 0
mclk_enabled: false
peripherals:
- name: i2s_audio_in

- name: fs_sdcard
type: fs_fat
sub_type: spi
version: default
config:
vfs_config:
# esp_vfs_fat supports FAT12/16/32 only; the SD card MUST be FAT32,
# not exFAT. Cards that fail to mount should be re-formatted with
# the official SD Card Formatter, not silently wiped here.
format_if_mount_failed: false
max_files: 5
sub_config:
# Seeed's official pin table (SD.begin(21) in the wiki example):
# CS = GPIO21, SCK = GPIO7, MISO = GPIO8, MOSI = GPIO9
# GPIO21 is shared with the user LED on the XIAO; CS wins.
cs_gpio_num: 21
# 10 MHz is a safe ceiling for the Sense expansion board's short SD
# card traces. If 0x107 (CRC) errors appear at boot, drop this to
# 1 MHz; the SDMMC driver still auto-negotiates to 400 kHz for the
# CMD0/ACMD41 init phase.
frequency: 10000000
peripherals:
- name: spi_sdcard
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
board: xiao_esp32s3_sense
chip: esp32s3
version: 1.0.0
description: "Seeed Studio XIAO ESP32-S3 Sense (ESP32-S3R8, OV2640 camera, PDM mic, microSD, user LED)"
manufacturer: "Seeed Studio"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
version: 1.0.0
# Peripherals Configuration for Seeed Studio XIAO ESP32-S3 Sense
#
# Bus allocation:
# I2C0 - camera SCCB (also used by XIAO header D4/D5 as I2C if needed later)
# SCL=GPIO39, SDA=GPIO40
# I2S0 - PDM microphone (pdm-in)
# CLK=GPIO42 (shared with D11/MTMS), DATA=GPIO41 (shared with D12/MTDI)
# SPI2 - on-board microSD card slot
# CS=GPIO21 (shared with user LED; SD takes the pin), SCK=GPIO7,
# MOSI=GPIO9, MISO=GPIO8
#
# The on-board user LED on GPIO21 is intentionally NOT registered as a
# peripheral: the Sense expansion board hardwires the SD card CS to the
# same pin, so the LED cannot be driven while the SD card is in use.

peripherals:
- name: i2c_master
type: i2c
role: master
config:
port: 0
pins:
sda: 40
scl: 39

- name: i2s_audio_in
type: i2s
role: master
format: pdm-in
config:
port: 0
sample_rate_hz: 16000
clk_src: I2S_CLK_SRC_DEFAULT
data_bit_width: 16
slot_bit_width: I2S_SLOT_BIT_WIDTH_AUTO
slot_mode: I2S_SLOT_MODE_MONO
slot_mask: I2S_PDM_SLOT_LEFT
data_fmt: I2S_PDM_DATA_FMT_PCM
pins:
clk: 42
din: 41

- name: spi_sdcard
type: spi
role: master
config:
spi_bus_config:
spi_port: SPI2_HOST
sclk_io_num: 7
mosi_io_num: 9
miso_io_num: 8
max_transfer_sz: 4096
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# XIAO ESP32-S3 Sense (ESP32-S3R8): 8 MB QIO flash @ 80 MHz
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y

# 8 MB octal PSRAM @ 80 MHz.
# The R8 module's PSRAM is wired to the chip's OPI peripheral, so no GPIO
# conflicts with the camera/SD/mic/LED wiring above.
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y

# PSRAM is mandatory here: esp_video places camera frame buffers in PSRAM
# (800x600 JPEG needs several hundred KB, which does not fit in internal SRAM
# once WiFi/LwIP, IM bindings, and the claw task tree are loaded).
# Put WiFi station / LwIP buffers in PSRAM to free ~50 KB of internal RAM.
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y

# FreeRTOS task stacks tagged CLAW_TASK_STACK_PREFER_PSRAM (claw_core,
# claw_memory, claw_event_router, cap_system, cap_scheduler, cap_im_*,
# cap_lua, ...) must be allowed to use external memory. OCT PSRAM keeps
# the stack accessible while flash cache is disabled, so leave the default y.
# Do NOT set CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=n (CoreS3 disables it
# only because it ships with QUAD PSRAM, which cannot).
#
# Keep instruction/rodata fetch from PSRAM disabled: 8 MB flash is enough
# for firmware, and flash-backed execution is faster than PSRAM-backed.
# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
# CONFIG_SPIRAM_RODATA is not set

# USB: Serial/JTAG is the on-board USB-C console.
# GPIO39-42 are reassigned to camera SCCB (39/40) and PDM mic (41/42),
# so JTAG over GPIO is not available. The internal USB PHY is used instead.
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y

# Camera: OV2640 over DVP 8-bit, 20 MHz XCLK.
# The Kconfig name is the actual default that menuconfig reports for
# esp_video's OV2640 driver on this chip:
# DVP 8-bit, 20 MHz XCLK, 640x480 @ 25 FPS, JPEG
# (The earlier 800x600 @ 30 FPS line was a guess; menuconfig does
# not actually expose that combination for the OV2640.)
CONFIG_ESP_BOARD_DEV_CAMERA_SUPPORT=y
CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE=y
CONFIG_CAMERA_OV2640=y
CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y
CONFIG_CAMERA_OV2640_DVP_JPEG_640X480_25FPS=y
CONFIG_CAMERA_OV2640_DVP_DEFAULT_FMT_JPEG_640X480_25FPS=y
CONFIG_APP_CLAW_LUA_MODULE_CAMERA=y

# Audio: bare PDM microphone on I2S0 (no codec IC, internal/dummy ADC)
CONFIG_ESP_BOARD_PERIPH_I2S_SUPPORT=y
CONFIG_CODEC_DATA_ADC_SUPPORT=y
CONFIG_APP_CLAW_LUA_MODULE_AUDIO=y