From d544692be94cd6cb7e9dc6bc5f508d591ef89c5b Mon Sep 17 00:00:00 2001 From: Kai <2857693944@qq.com> Date: Tue, 2 Apr 2024 08:41:04 +0800 Subject: [PATCH 1/5] Revert "fix: merge firmware sections, fix #56" This reverts commit b4d795329da36f35b5e4964420baac192aec9b8d. --- CHANGELOG.md | 4 ---- src/commands/mod.rs | 6 +++--- src/firmware.rs | 14 ++++++++------ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0df4be..c920c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,10 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use loaded memory address from ELF file or ihex file - Add timestamp in serial output -### Fixed - -- Merge gaps in firmware sections, #56 - ### Changed - No erase by default when flashing diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 3301611..30f0e51 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -91,7 +91,7 @@ impl fmt::Debug for RawCommand { } } -/// 0x01 - Set address and offset of the firmware +/// Set address and offset of the firmware, 0x01. #[derive(Debug)] pub struct SetWriteMemoryRegion { // 0x08000000 or 0x00000000 @@ -126,14 +126,14 @@ impl Command for SetReadMemoryRegion { } } -/// 0x02 - Flash or Memory operations +/// 0x02 subset #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Program { // wlink_erase EraseFlash = 0x01, // Before write firmware bytes, choice between 0x02 and 0x04 WriteFlash = 0x02, - // Write flash + // after write flash WriteFlashAndVerify = 0x04, /// Write Flash OP WriteFlashOP = 0x05, diff --git a/src/firmware.rs b/src/firmware.rs index 64896dc..2269ef4 100644 --- a/src/firmware.rs +++ b/src/firmware.rs @@ -39,7 +39,7 @@ pub enum Firmware { } impl Firmware { - /// Merge sections, and fill gap with 0xff + /// Merge sections w/ <= 256 bytes gap pub fn merge_sections(self) -> Result { if let Firmware::Sections(mut sections) = self { sections.sort_by_key(|s| s.address); @@ -49,14 +49,16 @@ impl Firmware { let mut last = it .next() .expect("firmware must has at least one section; qed"); - for sect in it { if let Some(gap) = sect.address.checked_sub(last.end_address()) { - if gap > 0 { - log::debug!("Merge firmware sections with gap: {}", gap); + if gap > 256 { + merged.push(last); + last = sect.clone(); + continue; + } else { + last.data.resize(last.data.len() + gap as usize, 0); + last.data.extend_from_slice(§.data); } - last.data.resize(last.data.len() + gap as usize, 0xff); // fill gap with 0xff - last.data.extend_from_slice(§.data); } else { return Err(anyhow::format_err!( "section address overflow: {:#010x} + {:#x}", From f763ed98834d7bd7ee7c17125acbf2a9839db271 Mon Sep 17 00:00:00 2001 From: Kai <2857693944@qq.com> Date: Tue, 2 Apr 2024 08:47:34 +0800 Subject: [PATCH 2/5] add an offset when writing to fit with wchlink --- src/commands/mod.rs | 6 +++--- src/firmware.rs | 6 +++--- src/main.rs | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 30f0e51..3301611 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -91,7 +91,7 @@ impl fmt::Debug for RawCommand { } } -/// Set address and offset of the firmware, 0x01. +/// 0x01 - Set address and offset of the firmware #[derive(Debug)] pub struct SetWriteMemoryRegion { // 0x08000000 or 0x00000000 @@ -126,14 +126,14 @@ impl Command for SetReadMemoryRegion { } } -/// 0x02 subset +/// 0x02 - Flash or Memory operations #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Program { // wlink_erase EraseFlash = 0x01, // Before write firmware bytes, choice between 0x02 and 0x04 WriteFlash = 0x02, - // after write flash + // Write flash WriteFlashAndVerify = 0x04, /// Write Flash OP WriteFlashOP = 0x05, diff --git a/src/firmware.rs b/src/firmware.rs index 2269ef4..b69f05b 100644 --- a/src/firmware.rs +++ b/src/firmware.rs @@ -39,7 +39,7 @@ pub enum Firmware { } impl Firmware { - /// Merge sections w/ <= 256 bytes gap + /// Merge sections w/ <= 4096 bytes gap pub fn merge_sections(self) -> Result { if let Firmware::Sections(mut sections) = self { sections.sort_by_key(|s| s.address); @@ -51,12 +51,12 @@ impl Firmware { .expect("firmware must has at least one section; qed"); for sect in it { if let Some(gap) = sect.address.checked_sub(last.end_address()) { - if gap > 256 { + if gap > 4096 { merged.push(last); last = sect.clone(); continue; } else { - last.data.resize(last.data.len() + gap as usize, 0); + last.data.resize(last.data.len() + gap as usize, 0xff); last.data.extend_from_slice(§.data); } } else { diff --git a/src/main.rs b/src/main.rs index 8e5f90d..7412b28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -351,6 +351,7 @@ fn main() -> Result<()> { if address != None { log::warn!("--address is ignored when flashing ELF or ihex"); } + let mut offset = 0; // may a trait of wchlink for section in sections { let start_address = sess.chip_family.fix_code_flash_start(section.address); @@ -359,7 +360,9 @@ fn main() -> Result<()> { section.data.len(), start_address ); - sess.write_flash(§ion.data, start_address)?; + log::debug!("offset: 0x{:08x}", offset); + sess.write_flash(§ion.data, start_address - offset)?; + offset += ((section.data.len() as u32 + 4095) / 4096) * 4096; } } } From 8c301b2c769636517933a6a8f5e3dac7a24a9c41 Mon Sep 17 00:00:00 2001 From: yekai <2857693944@qq.com> Date: Sun, 7 Apr 2024 22:46:00 +0800 Subject: [PATCH 3/5] add cli param to enable skip gap --- src/firmware.rs | 60 ++++++++++++++++++++++--------------------------- src/main.rs | 26 ++++++++++++++++----- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/firmware.rs b/src/firmware.rs index b69f05b..9bf51b2 100644 --- a/src/firmware.rs +++ b/src/firmware.rs @@ -38,41 +38,35 @@ pub enum Firmware { Sections(Vec
), } -impl Firmware { - /// Merge sections w/ <= 4096 bytes gap - pub fn merge_sections(self) -> Result { - if let Firmware::Sections(mut sections) = self { - sections.sort_by_key(|s| s.address); - let mut merged = vec![]; - - let mut it = sections.drain(0..); - let mut last = it - .next() - .expect("firmware must has at least one section; qed"); - for sect in it { - if let Some(gap) = sect.address.checked_sub(last.end_address()) { - if gap > 4096 { - merged.push(last); - last = sect.clone(); - continue; - } else { - last.data.resize(last.data.len() + gap as usize, 0xff); - last.data.extend_from_slice(§.data); - } - } else { - return Err(anyhow::format_err!( - "section address overflow: {:#010x} + {:#x}", - last.address, - last.data.len() - )); - } +/// Merge sections w/ <= max_tiny_gap bytes gap +pub fn fill_tiny_gap_between_sections(mut sections: Vec
, max_tiny_gap: u32) -> Result> { + sections.sort_by_key(|s| s.address); + let mut merged = vec![]; + + let mut it = sections.drain(0..); + let mut last = it + .next() + .expect("firmware must has at least one section; qed"); + for sect in it { + if let Some(gap) = sect.address.checked_sub(last.end_address()) { + if gap > max_tiny_gap { + merged.push(last); + last = sect.clone(); + continue; + } else { + last.data.resize(last.data.len() + gap as usize, 0); + last.data.extend_from_slice(§.data); } - merged.push(last); - Ok(Firmware::Sections(merged)) } else { - Ok(self) + return Err(anyhow::format_err!( + "section address overflow: {:#010x} + {:#x}", + last.address, + last.data.len() + )); } } + merged.push(last); + Ok(merged) } pub fn read_firmware_from_file>(path: P) -> Result { @@ -92,9 +86,9 @@ pub fn read_firmware_from_file>(path: P) -> Result { } FirmwareFormat::Binary => Ok(Firmware::Binary(raw)), FirmwareFormat::IntelHex => { - read_ihex(str::from_utf8(&raw)?).and_then(|f| f.merge_sections()) + read_ihex(str::from_utf8(&raw)?) } - FirmwareFormat::ELF => read_elf(&raw).and_then(|f| f.merge_sections()), + FirmwareFormat::ELF => read_elf(&raw), } } diff --git a/src/main.rs b/src/main.rs index 7412b28..cd9f8e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use anyhow::Result; use wlink::{ commands, dmi::DebugModuleInterface, - firmware::{read_firmware_from_file, Firmware}, + firmware::{fill_tiny_gap_between_sections, read_firmware_from_file, Firmware}, operations::ProbeSession, probe::WchLink, regs, RiscvChip, @@ -93,6 +93,9 @@ enum Commands { /// Erase flash before flashing #[arg(long, short, default_value = "false")] erase: bool, + /// Skip gap between sections + #[arg(long, short, default_value = "false")] + skip_gap: bool, /// Do not reset and run after flashing #[arg(long, short = 'R', default_value = "false")] no_run: bool, @@ -325,6 +328,7 @@ fn main() -> Result<()> { Flash { address, erase, + skip_gap, no_run, path, enable_sdi_print, @@ -341,25 +345,35 @@ fn main() -> Result<()> { match firmware { Firmware::Binary(data) => { + if skip_gap { + log::warn!("Skip gap is ignored when flashing binary"); + } let start_address = address.unwrap_or_else(|| sess.chip_family.code_flash_start()); log::info!("Flashing {} bytes to 0x{:08x}", data.len(), start_address); sess.write_flash(&data, start_address)?; } Firmware::Sections(sections) => { - // Flash section by section + let mut sections = sections.clone(); if address != None { log::warn!("--address is ignored when flashing ELF or ihex"); } + if skip_gap { + log::warn!("Skip gap is a experimental feature using a trait of wchlink!"); + sections = fill_tiny_gap_between_sections(sections, 4096)?; + } else { + // merge sections + sections = fill_tiny_gap_between_sections(sections, 0xFFFFFFFF)?; + } let mut offset = 0; // may a trait of wchlink for section in sections { let start_address = sess.chip_family.fix_code_flash_start(section.address); log::info!( - "Flashing {} bytes to 0x{:08x}", - section.data.len(), - start_address - ); + "Flashing {} bytes to 0x{:08x}", + section.data.len(), + start_address + ); log::debug!("offset: 0x{:08x}", offset); sess.write_flash(§ion.data, start_address - offset)?; offset += ((section.data.len() as u32 + 4095) / 4096) * 4096; From d1cf5acb8fa5d54a70a69d52ee605fd8aa5c5e3f Mon Sep 17 00:00:00 2001 From: yekai <2857693944@qq.com> Date: Sun, 7 Apr 2024 22:50:31 +0800 Subject: [PATCH 4/5] fill gap with 0xFF --- src/firmware.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firmware.rs b/src/firmware.rs index 9bf51b2..38bcda6 100644 --- a/src/firmware.rs +++ b/src/firmware.rs @@ -54,7 +54,7 @@ pub fn fill_tiny_gap_between_sections(mut sections: Vec
, max_tiny_gap: last = sect.clone(); continue; } else { - last.data.resize(last.data.len() + gap as usize, 0); + last.data.resize(last.data.len() + gap as usize, 0xFF); last.data.extend_from_slice(§.data); } } else { From e7dca4c79512fcb6f5478735358ae270bfc23bd8 Mon Sep 17 00:00:00 2001 From: yekai <2857693944@qq.com> Date: Mon, 8 Apr 2024 21:52:03 +0800 Subject: [PATCH 5/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c920c4c..f97445c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Rename ChipUID response to ESignature, #58 +- Add `--skip-gap` as a experimental option for `flash` subcommand to write a firmware which has more than 1 section, #40 & #56 ## [0.0.8] - 2024-03-30