A probe-rs flash loader for Espressif chips.
To build the flash loader:
$ cargo $(CHIP_NAME) # builds the flashing stub
$ target-gen elf target/$(RUST_TARGET)/release/esp-flashloader output/$(CHIP_NAME).yaml --update --name $(CHIP_NAME)-flashloaderExample for the updating the esp32c3 flash algorithm.
$ cargo esp32c3
$ target-gen elf target/riscv32imc-unknown-none-elf/release/esp-flashloader output/esp32c3.yaml --update --name esp32c3-flashloader| name | supported |
|---|---|
| esp32 | Y |
| esp32s2 | Y |
| esp32s3 | Y |
| esp32c2 | Y |
| esp32c3 | Y |
| esp32c5 | Y |
| esp32c6 | Y |
| esp32c61 | N |
| esp32h2 | Y |
| esp32p4 | N |
- Add a feature for the chip inside
Cargo.toml - Add a build alias to
.cargo/config.toml - Add the ROM API linker script inside the
lddirectory. - Inside the ROM API linker script, add a memory section detailing where the program will be loaded.
It's important to note that the algorithm cannot be loaded at the start of RAM, because probe-rs has a header it loads prior to the algo hence the 64K offset. IRAM origin and length can be obtained from esp-hal. Eg: ESP32-C3 memory map
MEMORY { /* Start 64k into the RAM region */ IRAM : ORIGIN = 0x40390000, LENGTH = 0x10000 }
- Add the following snippet to the
main()function insidebuild.rs, adapting it for the new chip name.#[cfg(feature = "esp32c3")] let chip = "esp32c3";
- Define
spiconfigfor your the target inflash.rs - Add your device to the table in
main.rsand calculate addresses. - Define your target's
STATE_ADDR#[cfg(feature = "esp32c3")] const STATE_ADDR: usize = 0x3FCC_0000;
- Follow the instructions above for building
- It may fail with:
rust-lld: error: undefined symbol: <symbol>- In this case, you need to add the missing method in the ROM API linker script.
- Eg. ESP32-C2 is missing
esp_rom_spiflash_attach:- Search the symbol in esp-idf
- Add it to the ROM API linker script:
PROVIDE(esp_rom_spiflash_attach = spi_flash_attach);
- Eg. ESP32-C2 is missing
- In this case, you need to add the missing method in the ROM API linker script.
- Use
target-genwithout theupdateflag to generate a new yaml algorithm. - Update the resulting yaml file
- Update
name - Update variants
name,type,core_access_optionsandmemory_map- The first
!Nvmblock represents the raw flash starting at 0 and up to the maximum supported external flash (check TRM for this, usually in "System and Memory/Features") - Next
!Ramblock corresponds to instruction bus for internal SRAM, see Internal Memory Address Mapping of TRM - Next
!Ramblock corresponds to data bus for internal SRAM, see Internal Memory Address Mapping of TRM - Next
!Nvmcorresponds to instruction bus for external memory, see External Memory Address Mapping of TRM - Next
!Nvmcorresponds to data bus for external memory, see External Memory Address Mapping of TRM
- The first
- Add
load_addressunderflash_algorithmsand assign the IRAMORIGINvalue (step 4). - Add
data_load_addressunderflash_algorithmsand assign an appropriate value residing in DRAM. - Add
transfer_encoding: Minizunderload_address - Upstream the new updates to probe-rs.