Skip to content

Conversation

@luoliwoshang
Copy link
Member

@luoliwoshang luoliwoshang commented Jan 8, 2026

Summary

Enable ESP32-C3 programs to exit cleanly in QEMU emulator by using semihosting _exit implementation.

Background

This PR builds on top of #1536 (feat/esp32c3-emulator-support) which added QEMU emulator configuration for ESP32-C3.

Previously, ESP32-C3 programs would crash in QEMU with "Illegal instruction" error because the default _exit implementation uses asm("unimp") which is invalid for QEMU emulator. The semihosting version uses ebreak instruction which QEMU can properly handle with the -semihosting flag.

Solution

This PR implements a three-part solution:

1. Upgrade to newlib-esp32 patch5

Update from esp-4.3.0_20250211-patch4 to esp-4.3.0_20250211-patch5 which includes the separation of _exit from syscalls.c to syscalls_exit.c (from goplus/newlib#10).

2. Remove conflicting _exit implementations

Remove the following stub implementations from the compile list:

  • libgloss/libnosys/_exit.c - generic stub for Xtensa targets
  • libgloss/riscv/sys_exit.c - RISC-V specific stub

After removing these, libgloss/riscv/semihost-sys_exit.c becomes the only _exit implementation and will be automatically linked from the existing static library (.a).

3. Enable semihosting in QEMU config

Add -semihosting flag to the QEMU command in targets/esp32c3-basic.json.

Changes

  • internal/crosscompile/compile/libc/newlibesp.go:
    • Update newlib version to esp-4.3.0_20250211-patch5
    • Remove libgloss/libnosys/_exit.c from Xtensa compile list
    • Remove libgloss/riscv/sys_exit.c from RISC-V compile list
  • internal/crosscompile/compile/libc/libc_test.go:
    • Update test expectations for new newlib version
  • targets/esp32c3-basic.json:
    • Add -semihosting flag to QEMU emulator command

Result

ESP32-C3 programs now run and exit cleanly in QEMU:

❯ llgo run -a -target=esp32c3-basic -emulator .
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
...
Hello from ESP32-C3 via USB Serial JTAG!
# Program exits cleanly without "Illegal instruction" error

Dependencies

Test Plan

  • Build ESP32-C3 target with updated newlib
  • Run program in QEMU emulator with -emulator flag
  • Verify program exits cleanly using semihosting
  • Confirm tests pass with updated version

🤖 Generated with Claude Code

@gemini-code-assist
Copy link

Summary of Changes

Hello @luoliwoshang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces support for the ESP32-C3 QEMU emulator by addressing an issue with the firmware image offset. Previously, a universal 4KB padding was applied to all ESP chip images, which caused the ESP32-C3's QEMU instance to fail due to an incorrect bootloader start address. The changes ensure that only ESP32 (Xtensa) chips receive this padding, allowing ESP32-C3 (RISC-V) images to boot correctly from offset 0x0 as required by its ROM bootloader.

Highlights

  • ESP32-C3 QEMU Emulator Support: Enabled QEMU emulator support for ESP32-C3 by correcting the image offset, resolving the "invalid header" error previously encountered.
  • Conditional Image Padding: Modified the firmware image generation logic to conditionally apply a 4KB zero-padding only for ESP32 (Xtensa) chips. ESP32-C3 (RISC-V) images now start at offset 0x0, aligning with its bootloader's expectation and removing unnecessary padding.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request correctly adjusts the firmware image creation for ESP32-C3 to support QEMU emulation by removing the 4KB padding that was causing boot failures. The change is specific to the esp32 chip, leaving other chips like esp32c3 unaffected, which is the correct approach. I have one suggestion regarding code maintainability to replace magic values with named constants.

Comment on lines +90 to +91
if chip == "esp32" {
outf.Write(make([]byte, 4096))

Choose a reason for hiding this comment

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

medium

To improve readability and maintainability, it's good practice to avoid magic values. Consider defining "esp32" and 4096 as named constants at a suitable scope (e.g., package-level). This makes the code's intent clearer and centralizes these values for easier updates in the future.

For example:

const (
    esp32ChipName          = "esp32"
    esp32BootloaderPadding = 4096
)

Then you can use these constants here:

if chip == esp32ChipName {
    outf.Write(make([]byte, esp32BootloaderPadding))
}

@xgopilot
Copy link

xgopilot bot commented Jan 8, 2026

Code Review Summary

The fix correctly addresses the ESP32-C3 QEMU boot issue. The implementation is functionally correct with clear documentation. Three noteworthy observations:

1. Testing Gap: No test coverage exists for firmware image generation. Consider adding tests to verify padding behavior for both chip variants.

2. Forward Compatibility: The hardcoded chip == "esp32" check works but may need updates when adding ESP32-S2/S3 (Xtensa) or ESP32-C6/H2 (RISC-V). Consider architecture-based checks for better maintainability.

3. Silent Failure Risk: The chip_id map lookup (line 97-100) silently returns 0 for unknown chips, which could generate incorrect firmware. Recommend adding validation after chip extraction.

Overall assessment: Ready to merge with these considerations noted for future improvements.

@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.00%. Comparing base (34b872c) to head (9d6314c).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1536   +/-   ##
=======================================
  Coverage   91.00%   91.00%           
=======================================
  Files          45       45           
  Lines       11955    11955           
=======================================
  Hits        10880    10880           
  Misses        899      899           
  Partials      176      176           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

luoliwoshang and others added 3 commits January 9, 2026 10:20
ESP32-C3 bootloader starts at flash offset 0x0, unlike ESP32 which
starts at 0x1000. The previous code added 4KB padding for all ESP
chips, causing QEMU to fail with "invalid header: 0x00000000" when
trying to boot ESP32-C3 images.

This fix only adds the 4KB padding for ESP32 (Xtensa), while ESP32-C3
(RISC-V) images now start at offset 0x0 as expected by its ROM
bootloader.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add emulator command configuration to esp32c3.json target file,
enabling ESP32-C3 programs to run in QEMU emulator with:
  llgo run -target=esp32c3 -emulator .

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add missing newlines at end of esp32c3.json and esp32c3-basic.json
to follow standard file formatting conventions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@luoliwoshang luoliwoshang force-pushed the feat/esp32c3-emulator-support branch from 66ef1c9 to 9d6314c Compare January 9, 2026 02:20
@luoliwoshang luoliwoshang changed the title feat: add ESP32-C3 QEMU emulator support fix(esp32c3): enable semihosting exit for QEMU emulator support Jan 9, 2026
@luoliwoshang luoliwoshang changed the title fix(esp32c3): enable semihosting exit for QEMU emulator support feat(esp32c3): QEMU emulator support Jan 9, 2026
@luoliwoshang luoliwoshang requested a review from xushiwei January 12, 2026 06:27
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.

1 participant