Skip to content

espressif: add ESP32-C5 support and the ESP32-C5-DevKitC-1-N8R8 board - #11297

Open
mikeysklar wants to merge 2 commits into
adafruit:mainfrom
mikeysklar:esp32c5-board
Open

espressif: add ESP32-C5 support and the ESP32-C5-DevKitC-1-N8R8 board#11297
mikeysklar wants to merge 2 commits into
adafruit:mainfrom
mikeysklar:esp32c5-board

Conversation

@mikeysklar

Copy link
Copy Markdown
Collaborator

What

Adds ESP32-C5 target support and the ESP32-C5-DevKitC-1-N8R8 board.

Why

First dual-band ESP32. These C6 differences build clean but fail at runtime.

C6 C5
Bootloader flash offset 0x0 0x2000
ADC1 channel 0 GPIO0 GPIO1
ROM download strap GPIO9 GPIO28
Crystal 40 MHz 48 MHz, so 20/24 MHz CPU invalid
TWAI classic TWAI-FD, so canio is off

reset_all_pins() must also skip the MSPI and USB pins.

No ESP-IDF bump: builds against the pointer already on main.

Hardware tested

Board ESP32-C5-DevKitC-1-N8R8, 8 MB flash, 8 MB PSRAM
Chip revision v1.2, 48 MHz crystal
Build host Ubuntu 24.04.4, ESP-IDF 2b900d1
Adafruit CircuitPython 10.3.0-28-gd48aa9e055-dirty on 2026-09-02; ESP32-C5-DevKitC-1-N8R8 with ESP32C5

Version string is from the build tree; contents match this branch.

Not tested: deep sleep, Windows, macOS.

How I tested it

import board, gc, analogio, digitalio, wifi

gc.collect(); print("HEAP", gc.mem_free())
a = analogio.AnalogIn(board.IO1); print("ADC", a.value); a.deinit()
d = digitalio.DigitalInOut(board.IO0)
d.switch_to_output(True); print("GPIO", d.value); d.deinit()
wifi.radio.connect("<ssid>", "<password>")
print("WIFI ch", wifi.radio.ap_info.channel, wifi.radio.ipv4_address)
HEAP 8262784
ADC 31099
GPIO True
WIFI ch 5 192.168.0.80

NeoPixel, BLE advertising and web workflow also verified.

Scope

This PR is board and target support only. 2.4 GHz works.

Off for this target, reasons in mpconfigport.mk:
canio, paralleldisplaybus, espcamera, espulp, memorymap, rgbmatrix,
touch, DAC, PDM, SDMMC.

Follow-up PRs

Two more complete 5 GHz. Neither is board-specific, so both are separate.

Change Touches
Next Scan 5 GHz channels on dual-band radios common-hal/wifi/ScannedNetworks.c, shared-bindings/wifi/Radio.c
Then CIRCUITPY_WIFI_BAND pins the radio to one band common-hal/wifi/Radio.c, docs/environment.rst

The second stacks on the first. Both are verified on this board.

The first raises the start_scanning_networks() default stop_channel, 11 to
165. Every board would then also scan channels 12-14.
Say if you want that split out or dropped.

AI assistance

Claude Code wrote most of this diff. I ran every hardware test.

C5 is the first dual-band ESP32. It differs from c6 in ways that build
cleanly but fail at run time:

- bootloader flash offset is 0x2000, not 0x0
- ADC1 channels start at GPIO1, not GPIO0
- efuse MAC registers are named like c61, not c6
- libphy.a references _rom_eco_version, so rom.version.ld must link
- USB-Serial-JTAG pads (GPIO13/14) are cleared by gpio_ll_func_sel(),
  so reset_all_pins() must skip them along with the flash/PSRAM MSPI
  pins and VDD_SPI
- boot button is GPIO28, not GPIO9 or GPIO0
- the 48MHz crystal leaves only 40/80/160/240MHz CPU valid
- TWAI is the newer TWAI-FD, so canio is off pending a backend
8MB flash, 8MB quad PSRAM, WS2812B on GPIO27, UART0 on GPIO11/12.

Flash mode is dio: qio locks the CPU during bootloader startup on this
board. PSRAM stays qio, which is the only mode C5 offers.
@mikeysklar

Copy link
Copy Markdown
Collaborator Author

zephyr-tests flaky: different tests fail each run. Re-run please?

@anecdata

anecdata commented Sep 3, 2026

Copy link
Copy Markdown
Member

Does CIRCUITPY_WIFI_BAND mean that the band can't be changed dynamicically from within CircuitPython code, or would this include some kind of AUTO (e.g., Espressif WIFI_BAND_MODE_AUTO) to allow either?

@mikeysklar

mikeysklar commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

It is a settings.toml key, and there is no Python API for it in these PRs. Unset, or any value other than 2.4 or 5, gives WIFI_BAND_MODE_AUTO, so both bands is the default.

The value is read when the radio starts, so toggling wifi.radio.enabled picks it up. A real wifi.radio.band property is one IDF call on the C5, but it is public API, so it needs stubs in the raspberrypi and zephyr-cp wifi ports too.

I can add another PR for dynamic band jumping between 2.4 and 5 GHz. Seems early to add that in, but if you think it is critical, sure.

@anecdata

anecdata commented Sep 3, 2026

Copy link
Copy Markdown
Member

AUTO should be fine. I gave only a cursory look at the esp-idf docs, but it seems like AUTO would allow an AP, for example, to be started on a 2.4 GHz channel, then later stopped and a 5 GHz AP started. And similar for a station connection. Or even, later, for monitor. I believe ESP-Now is 2.4 Ghz only, at least for now.

So I suppose the band selection would be mainly if someone wanted to limit the band use in their own locale.

@mikeysklar

Copy link
Copy Markdown
Collaborator Author

AUTO picks the strongest AP, so same-SSID networks land on 2.4 GHz. One room from my AP:

Setting Channel RSSI
unset (AUTO) 5 -51 dBm
CIRCUITPY_WIFI_BAND = "5" 149 -57 dBm

Three trials each.

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.

2 participants