Skip to content

Instantly share code, notes, and snippets.

@a-gavin
Last active March 18, 2023 23:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save a-gavin/1923ca5fdb633150303cb2fe00571d40 to your computer and use it in GitHub Desktop.
Save a-gavin/1923ca5fdb633150303cb2fe00571d40 to your computer and use it in GitHub Desktop.
ESP32-C3 and ESP32-C3 Notes

Overview

Initial dev environment setup for ESP32-C3 and ESP32-C6 programming, tailored towards Rust development. Some of this will also apply to the ESP32-C2 as well as the ESP32-H2 and ESP32-P4 when they are released.

  1. General Setup
  2. Setup USB JTAG
  3. Setup GPIO JTAG

General Setup

  • Install ESP tooling:

    NOTE: cargo-espflash is different than espflash. The former is useful when working with cargo. The latter is useful for developing in non-Rust environments.

    pip install esptool                                # Programs like espefuse.py, esptool.py
    cargo install cargo-espflash                       # So you can run "cargo espflash"
    rustup target install riscv32imc-unknown-none-elf  # ESP32-C3 rust toolchain
    rustup target install riscv32imac-unknown-none-elf # ESP32-C6 rust toolchain
  • Setup host-side debug-probe software:

    • probe-rs:

      NOTE: Must build from source with --features ftdi instead if using an FTDI-based debug probe.

      # If you want to setup an Embed.toml for your project
      cargo install cargo-embed
      
      # If you want to run manually (used later in verifying connectivity to board)
      cargo install probe-rs-cli
    • OpenOCD:

      # Will install OpenOCD into /opt/openocd/esp32 as `openocd-esp32`
      # NOTE: Remember to add /opt/openocd/esp32/bin to PATH
      git clone https://github.com/espressif/openocd-esp32.git
      cd openocd-esp32
      ./bootstrap
      ./configure --prefix=/opt/openocd/esp32/ --exec-prefix=/opt/openocd/esp32/ --program-suffix="-esp32"
      make -j $(nproc)
      sudo make install
      • If using a custom debug probe or debug probe without a config file in the fork, add its config file to the debug probe config file directory (in OpenOCD terms, the interface/ directory). If following the above setup verbatim, this directory is /opt/openocd/esp32/share/openocd/scripts/interface/. My debug probe is a FTDI-based 1BitSquared Tigard.
  • Setup access to serial devices (otherwise you'll need to be super user to flash your board):

    1. Add the following to an existing or new udev rule (see this guide for details):
      # ESP USB JTAG Serial
      ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
      
    2. Reload udev rules: sudo udevadm control --reload-rules && sudo udevadm trigger

Setup USB JTAG (Using cargo-espflash)

NOTE: ESP32-C6 boards are supported by cargo-espflash >= v2.0.0

  1. Connect a USB cable to either:
    • ESP32-C3 Micro USB port
    • ESP32-C6 USB-C port labeled "UART"
  2. Test the connection by running cargo espflash monitor. Note the serial output, including build date, in the following example:
    % cargo espflash monitor # This command will also display serial output from board UART
    [2023-03-15T06:54:11Z INFO ] Serial port: '/dev/ttyUSB0'
    [2023-03-15T06:54:11Z INFO ] Connecting...
    Commands:
        CTRL+R    Reset chip
        CTRL+C    Exit
    
    ESP-ROM:esp32c6-20220919
    Build:Sep 19 2022
    rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)

Assuming the above steps worked, you're now good to flash programs via USB JTAG. For example, flash your board with an example serial program when run in either the esp32c3-hal/ or esp32c6-hal/ directory of the ESP Rust HAL repo:

# Add --monitor to flash and then interact w/ board serial
cargo espflash flash --example serial_interrupts --features direct-boot --format=direct-boot

NOTE: When using direct-boot, the target is not flashed with the ESP IDF second-stage bootloader (as it is normally w/o direct-boot). The target instead boots directly from flash. See the ESP32-C6 Rust HAL for more info.

Setup GPIO JTAG

CAUTION: This process will irreversibly modify the behavior of your board.

By default, the ESP32-C3 and ESP32-C6 come with only USB JTAG configured. To use GPIO-based JTAG, you will need to burn fuses on the board using espefuse.py. There are a couple ways you can do this for each board. Here, I will show you how to enable GPIO JTAG while still allowing for USB JTAG.

In both chips, there is a fuse called JTAG_SEL_ENABLE which allows the user to select which JTAG method the chip will listen to. By burning this fuse (permanently setting it to 1), the chip will select GPIO JTAG when a chip-specific GPIO pin is strapped (connected to ground) on boot. For the ESP32-C3, this pin is GPIO 10. For the ESP32-C6, this pin is GPIO 15.

If your ESP32-C3 is like mine, the board revision is too early to have the JTAG_SEL_ENABLE fuse. As a workaround, burning the DIS_USB_JTAG fuse will enable GPIO JTAG at the cost of permanently disabling USB JTAG. That said, my board still seems to listen to USB JTAG even after flashing this, (possibly due to a bug in silicon). YMMV ¯_(ツ)_/¯. See this GitHub issue for more info.

For more details on JTAG selection, see section 6.2.4 of the ESP32-C6 Technical Reference Manual. The ESP32-C3 reference is sparse on details JTAG selection details, so see the previously-linked ESP32-C6 reference as are similar if not equivalent.

  • Burn JTAG_SEL_ENABLE fuse (sets it to 1 permanently)
    1. Connect a USB cable to the board (USB-C port labeled "UART" for the ESP32-C6)
    2. Run the following:
      espefuse.py summary --port /dev/ttyUSB0 # Should print False
      espefuse.py burn_efuse JTAG_SEL_ENABLE  # Prompts you to ensure correct efuse selected
      espefuse.py summary --port /dev/ttyUSB0 # Should print True
  • Test GPIO JTAG works
    1. Connect your debug probe to the board pins (in addition to GND and chosen power, 3.3V or 5V):

      Pin Function ESP32-C3 Pin ESP32-C6 Pin
      TMS 4 4
      TDI 5 5
      TCK 6 6
      TDO 7 7
      Any GND pin 10 15
    2. Verify your machine recognizes the board:

      • Via probe-rs:

        # No SWD err expected as ESP32C3 & ESP32C6 only implement JTAG
        % probe-rs-cli info # ESP32-C3
        Probing target via JTAG
        
        No DAP interface was found on the connected probe. Thus, ARM info cannot be printed.
        RISCV Chip:
                IDCODE: 0000005c25
                Version:      0
                Part:         5
                Manufacturer: 1554 (Espressif Systems (Shanghai)  Co Ltd)
        
        Probing target via SWD
        
        Error identifying target using protocol SWD: Probe does not support SWD
        
        % probe-rs-cli info # ESP32-C6
        Probing target via JTAG
        
        No DAP interface was found on the connected probe. Thus, ARM info cannot be printed.
        RISCV Chip:
                IDCODE: 000000dc25
                Version:      0
                Part:         13
                Manufacturer: 1554 (Espressif Systems (Shanghai)  Co Ltd)
        
        Probing target via SWD
        
        Error identifying target using protocol SWD: Probe does not support SWD
        
      • Via OpenOCD:

        # Substitute your debug probe config file for "interface/ftdi/tigard-jtag.cfg"
        % openocd-esp32 -f interface/ftdi/tigard-jtag.cfg -f target/esp32c3.cfg # ESP32-C3
        Open On-Chip Debugger v0.12.0-esp32-20230313 (2023-03-14-21:36)
        Licensed under GNU GPL v2
        For bug reports, read
                http://openocd.org/doc/doxygen/bugs.html
        Warn : Transport "jtag" was already selected
        Info : Listening on port 6666 for tcl connections
        Info : Listening on port 4444 for telnet connections
        Info : clock speed 2000 kHz
        Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)
        Info : datacount=2 progbufsize=16
        Info : Examined RISC-V core; found 1 harts
        Info :  hart 0: XLEN=32, misa=0x40101104
        Info : starting gdb server for esp32c3 on 3333
        Info : Listening on port 3333 for gdb connections
        
        % openocd-esp32 -f interface/ftdi/tigard-jtag.cfg -f target/esp32c6.cfg # ESP32-C6
        Open On-Chip Debugger v0.12.0-esp32-20230313 (2023-03-14-21:36)
        Licensed under GNU GPL v2
        For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
        Warn : Transport "jtag" was already selected
        Info : Listening on port 6666 for tcl connections
        Info : Listening on port 4444 for telnet connections
        Info : clock speed 2000 kHz
        Info : JTAG tap: esp32c6.cpu tap/device found: 0x0000dc25 (mfg: 0x612 (Espressif Systems), part: 0x000d, ver: 0x0)
        Info : datacount=2 progbufsize=16
        Info : Examined RISC-V core; found 2 harts
        Info :  hart 0: XLEN=32, misa=0x40903105
        Info : starting gdb server for esp32c6 on 3333
        Info : Listening on port 3333 for gdb connections
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment