Skip to content

Commit 95ebce0

Browse files
authored
Tune flash loaders (#7)
* Add aliasses to simplify building * Use block erase and bigger write page
1 parent 76d96f0 commit 95ebce0

File tree

3 files changed

+40
-34
lines changed

3 files changed

+40
-34
lines changed

.cargo/config.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
1+
[alias]
2+
esp32c2 = "build --release --features esp32c2 --target riscv32imc-unknown-none-elf"
3+
esp32c3 = "build --release --features esp32c3 --target riscv32imc-unknown-none-elf"
4+
esp32c6 = "build --release --features esp32c6 --target riscv32imac-unknown-none-elf"
5+
esp32h2 = "build --release --features esp32h2 --target riscv32imac-unknown-none-elf"
26

37
[target.'cfg(any(target_arch = "xtensa", target_arch = "riscv32"))']
48
rustflags = [

README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,24 @@ A probe-rs flash loader for Espressif chips.
55
To build the flash loader:
66

77
```bash
8-
$ cargo build --release --feature $(CHIP_NAME) --target $(RUST_TARGET) # builds the flashing stub
8+
$ cargo $(CHIP_NAME) # builds the flashing stub
99
$ target-gen elf target/$(RUST_TARGET)/release/esp-flashloader output/$(CHIP_NAME).yaml --update --name $(CHIP_NAME)-flashloader
1010
```
1111

1212
Example for the updating the `esp32c3` flash algorithm.
1313

1414
```bash
15-
$ cargo build --release --features esp32c3 --target riscv32imc-unknown-none-elf
15+
$ cargo esp32c3
1616
$ target-gen elf target/riscv32imc-unknown-none-elf/release/esp-flashloader output/esp32c3.yaml --update --name esp32c3-flashloader
1717
```
1818

1919
## Chip support
2020

2121
| name | supported |
2222
| ------- | --------- |
23+
| esp32 | N |
24+
| esp32s2 | N |
25+
| esp32s3 | N |
2326
| esp32c2 | Y |
2427
| esp32c3 | Y |
2528
| esp32c6 | Y |
@@ -28,8 +31,9 @@ $ target-gen elf target/riscv32imc-unknown-none-elf/release/esp-flashloader outp
2831
## Adding new chips
2932

3033
1. Add a feature for the chip inside `Cargo.toml`
31-
2. Add the [ROM API linker script](https://github.com/search?q=repo%3Aespressif%2Fesp-idf++path%3A*rom.api.ld&type=code) inside the `ld` directory.
32-
3. Inside the ROM API linker script, add a memory section detailing where the program will be loaded.
34+
2. Add a build alias to `.cargo/config.toml`
35+
3. Add the [ROM API linker script](https://github.com/search?q=repo%3Aespressif%2Fesp-idf++path%3A*rom.api.ld&type=code) inside the `ld` directory.
36+
4. Inside the ROM API linker script, add a memory section detailing where the program will be loaded.
3337
```c
3438
MEMORY {
3539
/* Start 64k into the RAM region */
@@ -38,20 +42,20 @@ $ target-gen elf target/riscv32imc-unknown-none-elf/release/esp-flashloader outp
3842
```
3943
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.
4044
IRAM origin and length can be obtained from esp-hal. Eg: [ESP32-C3 memory map](https://github.com/esp-rs/esp-hal/blob/ff80b69183739d04d1cb154b8232be01c0b26fd9/esp32c3-hal/ld/db-esp32c3-memory.x#L5-L22)
41-
4. Add the following snippet to the `main()` function inside `build.rs`, adapting it for the new chip name.
45+
5. Add the following snippet to the `main()` function inside `build.rs`, adapting it for the new chip name.
4246
```rust
4347
#[cfg(feature = "esp32c3")]
4448
let chip = "esp32c3";
4549
```
46-
5. [Define `spiconfig` for your the target in `main.rs`](https://github.com/search?q=repo%3Aespressif%2Fesp-idf+ets_efuse_get_spiconfig+path%3A*c3*&type=code)
47-
6. Follow the instructions above for building
50+
6. [Define `spiconfig` for your the target in `main.rs`](https://github.com/search?q=repo%3Aespressif%2Fesp-idf+ets_efuse_get_spiconfig+path%3A*c3*&type=code)
51+
7. Follow the instructions above for building
4852
- It may fail with: `rust-lld: error: undefined symbol: <symbol>`
4953
- In this case, you need to add the missing method in the ROM API linker script.
5054
- Eg. ESP32-C2 is missing `esp_rom_spiflash_attach`:
5155
1. [Search the symbol in esp-idf](https://github.com/search?q=repo%3Aespressif%2Fesp-idf+esp_rom_spiflash_attach+path%3A*c2*&type=code)
5256
2. Add it to the ROM API linker script: `PROVIDE(esp_rom_spiflash_attach = spi_flash_attach);`
53-
7. Use `target-gen` _without_ the `update` flag to generate a new yaml algorithm.
54-
8. Update the resulting yaml file
57+
8. Use `target-gen` _without_ the `update` flag to generate a new yaml algorithm.
58+
9. Update the resulting yaml file
5559
1. Update `name`
5660
2. Update variants `name`, `type`, `core_access_options` and `memory_map`
5761
- The first `!Nvm` block 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")

src/main.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
use panic_never as _;
1111

12-
const FLASH_SECTOR_SIZE: u32 = 4096;
12+
const FLASH_BLOCK_SIZE: u32 = 65536;
1313

1414
#[cfg(not(any(target_arch = "xtensa", target_arch = "riscv32")))]
1515
compile_error!("specify the target with `--target`");
@@ -54,12 +54,10 @@ macro_rules! dprintln {
5454
#[allow(unused)]
5555
extern "C" {
5656

57-
// fn esp_rom_spiflash_wait_idle(/* esp_rom_spiflash_chip_t *spi */);
5857
// fn esp_rom_spiflash_write_encrypted_enable();
5958
// fn esp_rom_spiflash_write_encrypted_disable();
6059
// fn esp_rom_spiflash_write_encrypted(addr: u32, data: *const u8, len: u32);
6160
// fn esp_rom_spiflash_config_param();
62-
// fn esp_rom_spiflash_read_user_cmd();
6361
// fn esp_rom_spiflash_select_qio_pins();
6462
// fn esp_rom_spi_flash_auto_sus_res();
6563
// fn esp_rom_spi_flash_send_resume();
@@ -77,6 +75,7 @@ extern "C" {
7775
fn esp_rom_spiflash_write(dest_addr: u32, data: *const u8, len: u32) -> i32;
7876
/// address (4 byte alignment), data, length
7977
fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32;
78+
fn esp_rom_spiflash_read_user_cmd(status: *mut u32, cmd: u8) -> i32;
8079
fn esp_rom_spiflash_unlock() -> i32;
8180
// fn esp_rom_spiflash_lock(); // can't find in idf defs?
8281
fn esp_rom_spiflash_attach(config: u32, legacy: bool);
@@ -87,6 +86,20 @@ extern "C" {
8786

8887
}
8988

89+
unsafe fn wait_for_idle() -> i32 {
90+
const SR_WIP: u32 = 1 << 0;
91+
92+
let mut status = SR_WIP;
93+
while status & SR_WIP != 0 {
94+
let res = esp_rom_spiflash_read_user_cmd(&mut status, 0x05);
95+
if res != 0 {
96+
return res;
97+
}
98+
}
99+
100+
0
101+
}
102+
90103
/// Setup the device for the
91104
#[no_mangle]
92105
#[inline(never)]
@@ -103,11 +116,6 @@ pub unsafe extern "C" fn Init(_adr: u32, _clk: u32, _fnc: u32) -> i32 {
103116

104117
esp_rom_spiflash_attach(spiconfig, false);
105118

106-
let res = esp_rom_spiflash_unlock();
107-
if res != 0 {
108-
return res;
109-
}
110-
111119
INITD = true;
112120
}
113121

@@ -121,12 +129,7 @@ pub unsafe extern "C" fn Init(_adr: u32, _clk: u32, _fnc: u32) -> i32 {
121129
#[inline(never)]
122130
pub unsafe extern "C" fn EraseSector(adr: u32) -> i32 {
123131
dprintln!("ERASE @ {}", adr);
124-
let res = esp_rom_spiflash_erase_sector(adr / FLASH_SECTOR_SIZE);
125-
if res != 0 {
126-
return res;
127-
}
128-
129-
0
132+
esp_rom_spiflash_erase_block(adr / FLASH_BLOCK_SIZE)
130133
}
131134

132135
#[no_mangle]
@@ -146,18 +149,13 @@ pub unsafe extern "C" fn ProgramPage(adr: u32, sz: u32, buf: *const u8) -> i32 {
146149

147150
dprintln!("PROGRAM {} bytes @ {}", sz, adr);
148151

149-
let res = esp_rom_spiflash_write(adr, buf, sz);
150-
if res != 0 {
151-
return res;
152-
}
153-
154-
0
152+
esp_rom_spiflash_write(adr, buf, sz)
155153
}
156154

157155
#[no_mangle]
158156
#[inline(never)]
159-
pub extern "C" fn UnInit(_fnc: u32) -> i32 {
160-
0
157+
pub unsafe extern "C" fn UnInit(_fnc: u32) -> i32 {
158+
wait_for_idle()
161159
}
162160

163161
#[allow(non_upper_case_globals)]
@@ -171,7 +169,7 @@ pub static FlashDevice: FlashDeviceDescription = FlashDeviceDescription {
171169
dev_addr: 0x0,
172170
device_size: 0x4000000, /* Max of 64MB */
173171
// TODO change per variant?
174-
page_size: 2048,
172+
page_size: 16384,
175173
_reserved: 0,
176174
empty: 0xFF,
177175
program_time_out: 1000,
@@ -188,7 +186,7 @@ const fn sectors() -> [FlashSector; 512] {
188186
let mut sectors = [FlashSector::default(); 512];
189187

190188
sectors[0] = FlashSector {
191-
size: 0x1000, // 4k
189+
size: 0x10000, // 64k
192190
address: 0x0,
193191
};
194192
sectors[1] = SECTOR_END;

0 commit comments

Comments
 (0)