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 | Y |
| esp32h2 | Y |
| esp32p4 | Y |
- 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, and where its data will be stored.
It's important to note that the algorithm cannot be loaded at the start of RAM, because probe-rs loads a short header prior to the algo. IRAM origin and length can be obtained from esp-hal. Eg: ESP32-C3 memory map RWDATA should be accessible via the data bus, should be at least 96K in size, and must not overlap with IRAM. IRAM and RWDATA must not overlap with instruction/data caches or the memory reserved for ROM functions.
MEMORY { /* Start 64k into the RAM region */ IRAM : ORIGIN = 0x40390000, LENGTH = 0x10000 RWDATA : ORIGIN = 0x3FCB0000, LENGTH = 0x20000 }
- 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 device specific data in
chip/<chip_name>.rs, and add the file to the list of paths inmain.rs. Take an existing chip as a reference. Obtain the ROM memory init addresses from the ROM code elf files. - (Optional) Implement code necessary to set maximum CPU speed.
- 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.