Skip to content

Commit b8a9854

Browse files
authored
Add support for flashing S2 via CDC UART (#228)
* Correct reset_after_flash behavior * Add support for flashing S2 via CDC UART This change makes it possible to flash an ESP32-S2 via CDC UART.
1 parent 99d91e9 commit b8a9854

File tree

7 files changed

+89
-21
lines changed

7 files changed

+89
-21
lines changed

espflash/src/chip/esp32/esp32s2.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ use crate::{
66
connection::Connection,
77
elf::{FirmwareImage, FlashFrequency, FlashMode},
88
error::UnsupportedImageFormatError,
9-
flasher::FlashSize,
9+
flash_target::MAX_RAM_BLOCK_SIZE,
10+
flasher::{FlashSize, FLASH_WRITE_SIZE},
1011
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
1112
Chip, Error, PartitionTable,
1213
};
1314

15+
const MAX_USB_BLOCK_SIZE: usize = 0x800;
16+
1417
pub struct Esp32s2;
1518

1619
pub const PARAMS: Esp32Params = Esp32Params::new(
@@ -79,6 +82,22 @@ impl ChipType for Esp32s2 {
7982
Ok(40)
8083
}
8184

85+
fn flash_write_size(&self, connection: &mut Connection) -> Result<usize, Error> {
86+
Ok(if self.connection_is_usb_otg(connection)? {
87+
MAX_USB_BLOCK_SIZE
88+
} else {
89+
FLASH_WRITE_SIZE
90+
})
91+
}
92+
93+
fn max_ram_block_size(&self, connection: &mut Connection) -> Result<usize, Error> {
94+
Ok(if self.connection_is_usb_otg(connection)? {
95+
MAX_USB_BLOCK_SIZE
96+
} else {
97+
MAX_RAM_BLOCK_SIZE
98+
})
99+
}
100+
82101
fn get_flash_segments<'a>(
83102
image: &'a dyn FirmwareImage<'a>,
84103
bootloader: Option<Vec<u8>>,
@@ -110,6 +129,13 @@ impl ReadEFuse for Esp32s2 {
110129
}
111130

112131
impl Esp32s2 {
132+
fn connection_is_usb_otg(&self, connection: &mut Connection) -> Result<bool, Error> {
133+
const UARTDEV_BUF_NO: u32 = 0x3FFFFD14; // Address which indicates OTG in use
134+
const UARTDEV_BUF_NO_USB_OTG: u32 = 2; // Value of UARTDEV_BUF_NO when OTG is in use
135+
136+
Ok(connection.read_reg(UARTDEV_BUF_NO)? == UARTDEV_BUF_NO_USB_OTG)
137+
}
138+
113139
fn get_flash_version(&self, connection: &mut Connection) -> Result<u32, Error> {
114140
let blk1_word3 = self.read_efuse(connection, 8)?;
115141
let flash_version = (blk1_word3 >> 21) & 0xf;

espflash/src/chip/mod.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use crate::{
1111
connection::Connection,
1212
elf::{FirmwareImage, FlashFrequency, FlashMode},
1313
error::ChipDetectError,
14-
flash_target::{Esp32Target, Esp8266Target, FlashTarget, RamTarget},
15-
flasher::{FlashSize, SpiAttachParams},
14+
flash_target::{Esp32Target, Esp8266Target, FlashTarget, RamTarget, MAX_RAM_BLOCK_SIZE},
15+
flasher::{FlashSize, SpiAttachParams, FLASH_WRITE_SIZE},
1616
image_format::{ImageFormat, ImageFormatId},
1717
Error, PartitionTable,
1818
};
@@ -91,6 +91,14 @@ pub trait ChipType: ReadEFuse {
9191
fn supports_target(target: &str) -> bool {
9292
Self::SUPPORTED_TARGETS.contains(&target)
9393
}
94+
95+
fn flash_write_size(&self, _connection: &mut Connection) -> Result<usize, Error> {
96+
Ok(FLASH_WRITE_SIZE)
97+
}
98+
99+
fn max_ram_block_size(&self, _connection: &mut Connection) -> Result<usize, Error> {
100+
Ok(MAX_RAM_BLOCK_SIZE)
101+
}
94102
}
95103

96104
pub trait ReadEFuse {
@@ -295,8 +303,12 @@ impl Chip {
295303
}
296304
}
297305

298-
pub fn ram_target(&self, entry: Option<u32>) -> Box<dyn FlashTarget> {
299-
Box::new(RamTarget::new(entry))
306+
pub fn ram_target(
307+
&self,
308+
entry: Option<u32>,
309+
max_ram_block_size: usize,
310+
) -> Box<dyn FlashTarget> {
311+
Box::new(RamTarget::new(entry, max_ram_block_size))
300312
}
301313

302314
pub fn flash_target(
@@ -408,6 +420,28 @@ impl Chip {
408420
Chip::Esp8266 => Esp8266::flash_frequency_encodings(),
409421
}
410422
}
423+
424+
pub fn flash_write_size(&self, connection: &mut Connection) -> Result<usize, Error> {
425+
match self {
426+
Chip::Esp32 => Esp32.flash_write_size(connection),
427+
Chip::Esp32c2 => Esp32c2.flash_write_size(connection),
428+
Chip::Esp32c3 => Esp32c3.flash_write_size(connection),
429+
Chip::Esp32s2 => Esp32s2.flash_write_size(connection),
430+
Chip::Esp32s3 => Esp32s3.flash_write_size(connection),
431+
Chip::Esp8266 => Esp8266.flash_write_size(connection),
432+
}
433+
}
434+
435+
pub fn max_ram_block_size(&self, connection: &mut Connection) -> Result<usize, Error> {
436+
match self {
437+
Chip::Esp32 => Esp32.max_ram_block_size(connection),
438+
Chip::Esp32c2 => Esp32c2.max_ram_block_size(connection),
439+
Chip::Esp32c3 => Esp32c3.max_ram_block_size(connection),
440+
Chip::Esp32s2 => Esp32s2.max_ram_block_size(connection),
441+
Chip::Esp32s3 => Esp32s3.max_ram_block_size(connection),
442+
Chip::Esp8266 => Esp8266.max_ram_block_size(connection),
443+
}
444+
}
411445
}
412446

413447
pub(crate) fn bytes_to_mac_addr(bytes: &[u8]) -> String {

espflash/src/connection.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ pub fn reset_after_flash(serial: &mut dyn SerialPort, pid: u16) -> Result<(), se
290290

291291
serial.write_request_to_send(false)?;
292292
} else {
293-
serial.write_data_terminal_ready(false)?;
294293
serial.write_request_to_send(true)?;
295294

296295
sleep(Duration::from_millis(100));

espflash/src/flash_target/esp32.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::connection::{Connection, USB_SERIAL_JTAG_PID};
33
use crate::elf::RomSegment;
44
use crate::error::Error;
55
use crate::flash_target::FlashTarget;
6-
use crate::flasher::{SpiAttachParams, FLASH_SECTOR_SIZE, FLASH_WRITE_SIZE};
6+
use crate::flasher::{SpiAttachParams, FLASH_SECTOR_SIZE};
77
use crate::Chip;
88
use flate2::write::{ZlibDecoder, ZlibEncoder};
99
use flate2::Compression;
@@ -94,7 +94,8 @@ impl FlashTarget for Esp32Target {
9494
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best());
9595
encoder.write_all(&segment.data)?;
9696
let compressed = encoder.finish()?;
97-
let block_count = (compressed.len() + FLASH_WRITE_SIZE - 1) / FLASH_WRITE_SIZE;
97+
let flash_write_size = self.chip.flash_write_size(connection)?;
98+
let block_count = (compressed.len() + flash_write_size - 1) / flash_write_size;
9899
let erase_count = (segment.data.len() + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE;
99100

100101
// round up to sector size
@@ -106,15 +107,15 @@ impl FlashTarget for Esp32Target {
106107
connection.command(Command::FlashDeflateBegin {
107108
size: erase_size,
108109
blocks: block_count as u32,
109-
block_size: FLASH_WRITE_SIZE as u32,
110+
block_size: flash_write_size as u32,
110111
offset: addr,
111112
supports_encryption: self.chip != Chip::Esp32 && !self.use_stub,
112113
})?;
113114
Ok(())
114115
},
115116
)?;
116117

117-
let chunks = compressed.chunks(FLASH_WRITE_SIZE);
118+
let chunks = compressed.chunks(flash_write_size);
118119

119120
let (_, chunk_size) = chunks.size_hint();
120121
let chunk_size = chunk_size.unwrap_or(0) as u64;

espflash/src/flash_target/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub use esp32::Esp32Target;
1111
pub use esp8266::Esp8266Target;
1212
pub use ram::RamTarget;
1313

14+
pub(crate) use ram::MAX_RAM_BLOCK_SIZE;
15+
1416
pub trait FlashTarget {
1517
fn begin(&mut self, connection: &mut Connection) -> Result<(), Error>;
1618
fn write_segment(

espflash/src/flash_target/ram.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use crate::error::Error;
55
use crate::flash_target::FlashTarget;
66
use bytemuck::{Pod, Zeroable};
77

8+
pub(crate) const MAX_RAM_BLOCK_SIZE: usize = 0x1800;
9+
810
#[derive(Zeroable, Pod, Copy, Clone)]
911
#[repr(C)]
1012
struct EntryParams {
@@ -14,17 +16,18 @@ struct EntryParams {
1416

1517
pub struct RamTarget {
1618
entry: Option<u32>,
19+
block_size: usize,
1720
}
1821

1922
impl RamTarget {
20-
pub fn new(entry: Option<u32>) -> Self {
21-
RamTarget { entry }
23+
pub fn new(entry: Option<u32>, block_size: usize) -> Self {
24+
RamTarget { entry, block_size }
2225
}
2326
}
2427

2528
impl Default for RamTarget {
2629
fn default() -> Self {
27-
Self::new(None)
30+
Self::new(None, MAX_RAM_BLOCK_SIZE)
2831
}
2932
}
3033

@@ -38,21 +41,18 @@ impl FlashTarget for RamTarget {
3841
connection: &mut Connection,
3942
segment: RomSegment,
4043
) -> Result<(), Error> {
41-
const MAX_RAM_BLOCK_SIZE: usize = 0x1800;
42-
4344
let padding = 4 - segment.data.len() % 4;
44-
let block_count =
45-
(segment.data.len() + padding + MAX_RAM_BLOCK_SIZE - 1) / MAX_RAM_BLOCK_SIZE;
45+
let block_count = (segment.data.len() + padding + self.block_size - 1) / self.block_size;
4646

4747
connection.command(Command::MemBegin {
4848
size: segment.data.len() as u32,
4949
blocks: block_count as u32,
50-
block_size: MAX_RAM_BLOCK_SIZE as u32,
50+
block_size: self.block_size as u32,
5151
offset: segment.addr,
5252
supports_encryption: false,
5353
})?;
5454

55-
for (i, block) in segment.data.chunks(MAX_RAM_BLOCK_SIZE).enumerate() {
55+
for (i, block) in segment.data.chunks(self.block_size).enumerate() {
5656
connection.command(Command::MemData {
5757
sequence: i as u32,
5858
pad_to: 4,

espflash/src/flasher.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,10 @@ impl Flasher {
257257
// Load flash stub
258258
let stub = FlashStub::get(self.chip);
259259

260-
let mut ram_target = self.chip.ram_target(Some(stub.entry()));
260+
let mut ram_target = self.chip.ram_target(
261+
Some(stub.entry()),
262+
self.chip.max_ram_block_size(&mut self.connection)?,
263+
);
261264
ram_target.begin(&mut self.connection).flashing()?;
262265

263266
let (text_addr, text) = stub.text();
@@ -513,7 +516,10 @@ impl Flasher {
513516
pub fn load_elf_to_ram(&mut self, elf_data: &[u8]) -> Result<(), Error> {
514517
let image = ElfFirmwareImage::try_from(elf_data)?;
515518

516-
let mut target = self.chip.ram_target(Some(image.entry()));
519+
let mut target = self.chip.ram_target(
520+
Some(image.entry()),
521+
self.chip.max_ram_block_size(&mut self.connection)?,
522+
);
517523
target.begin(&mut self.connection).flashing()?;
518524

519525
if image.rom_segments(self.chip).next().is_some() {

0 commit comments

Comments
 (0)