Skip to content

Add Xtensa (ESP32-S2/S3) target support - #168

Open
truongsinh wants to merge 1 commit into
zephyrproject-rtos:mainfrom
unda-os:xtensa-support
Open

Add Xtensa (ESP32-S2/S3) target support#168
truongsinh wants to merge 1 commit into
zephyrproject-rtos:mainfrom
unda-os:xtensa-support

Conversation

@truongsinh

@truongsinh truongsinh commented Jul 16, 2026

Copy link
Copy Markdown

This adds Xtensa support for building and running Rust applications on ESP32-S3 (and, mapped but untested, ESP32-S2/ESP32) boards:

  • CMake target mapping: CONFIG_XTENSA SoC series → xtensa-esp32s3-none-elf / -s2 / -esp32. These target specs are upstream rustc tier 3 (Add no_std Xtensa targets support rust-lang/rust#125141, #126380), but official rustc ships without the Xtensa LLVM backend, so building requires the esp-rs Rust toolchain on PATH plus build-std (e.g. CARGO_UNSTABLE_BUILD_STD=core,alloc). The mapping comment says so.
  • Kconfig: allow RUST_SUPPORTED on XTENSA.
  • kconfig codegen: emit hex values wider than 32 bits as u64 instead of usize — ESP32-S3's CONFIG_SOC_GPIO_VALID_GPIO_MASK (49 bits) previously generated pub const …: usize = 0x1FFFFFFFFFFFF; which is a hard error on 32-bit targets.

Verified on real hardware: samples/hello_world built for heltec_wireless_tracker/esp32s3/procpu with the esp 1.93 toolchain boots and logs Hello world from Rust on heltec_wireless_tracker over the USB-Serial-JTAG console. Also re-verified the existing ARM path (qemu_cortex_m3 boots, nrf52840dk builds) with the same tree.

One adjacent observation while testing (not part of this PR): boards whose GPIO controllers use single-cell specifiers (e.g. mps2/an385) make the generated devicetree.rs call GpioPin::new with one argument too few — can file an issue with details if useful.

- map CONFIG_XTENSA SoC series to xtensa-*-none-elf rust targets (these
  exist upstream as tier 3 but need the esp-rs toolchain's LLVM backend)
- allow RUST_SUPPORTED on XTENSA
- kconfig codegen: emit hex values wider than 32 bits as u64 (ESP32-S3
  GPIO masks overflow usize on 32-bit targets)

Verified on heltec_wireless_tracker/esp32s3/procpu hardware: hello_world
boots and logs, built with the esp 1.93 toolchain and
CARGO_UNSTABLE_BUILD_STD=core,alloc.

Signed-off-by: TruongSinh Tran-Nguyen <i@truongsinh.pro>
Comment thread zephyr-build/src/lib.rs
writeln!(&mut f, "pub const {}: usize = {};", &caps[1], &caps[2]).unwrap();
// Hex values wider than 32 bits (e.g. ESP32-S3 GPIO masks) don't
// fit usize on 32-bit targets; widen the type to match the value.
let value = u64::from_str_radix(&caps[2][2..], 16).unwrap_or(u64::MAX);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will this also emit u64 instead of usize even on 64-bit targets? Just curious if this was considered and if it could cause any issues.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, but only for hex values above u32::MAX, and it keys on the value rather than the target, so a given constant is u64 everywhere or usize everywhere. That keeps the type portable instead of target-conditional. On 64-bit there's no truncation either way since usize is already 64-bit; on 32-bit the u64 is what avoids the silent truncation this fixes. The only cost is that a >u32 hex const is u64, so a usize consumer needs a cast, but those are rare (large masks like GPIO). If uniformity matters more than that, always emitting u64 for hex is the alternative, at the cost of small values losing the ergonomic usize.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm, it's a bit annoying that you'd get usize mixed with u64 on 64-bit systems where a uniform representation is available.

I think one of the following would be more sane,

  1. u32 with promotion to u64 when necessary - for all targets
  2. usize with promotion to u64 only when there is a target limitation

@d3zd3z What do you think?

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