From d483b235bf6b67d3f08083296f618b46dbf34fc5 Mon Sep 17 00:00:00 2001 From: Andelf Date: Tue, 3 Oct 2023 02:50:39 +0800 Subject: [PATCH] chore: ch32x035 verfied --- src/commands.rs | 8 +++-- src/flash_op.rs | 73 +++++++++++++++---------------------- src/lib.rs | 2 +- src/main.rs | 4 ++- src/operations.rs | 92 ++++++++++++++++++++++++++--------------------- src/transport.rs | 26 ++++++++------ 6 files changed, 104 insertions(+), 101 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 32e8aea..6bb1eee 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -38,8 +38,10 @@ pub trait Response { if len != resp[3..].len() { return Err(Error::InvalidPayloadLength); } - let payload = resp[3..3 + len].to_vec(); - Err(Error::Protocol(reason, payload)) + if reason == 0x55 { + return Err(Error::Protocol(reason, resp.to_vec())); + } + Err(Error::Protocol(reason, resp.to_vec())) } else if resp[0] == 0x82 { let len = resp[2] as usize; if len != resp[3..].len() { @@ -159,6 +161,7 @@ pub enum FlashProtect { Protect = 0x03, Unprotect = 0x02, // dummy 0xf0 mask + // prefix byte 0xe7 ? for ch32x035 ProtectEx = 0xf3, // with 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // dummy 0xf0 mask UnprotectEx = 0xf2, // with 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -412,6 +415,7 @@ impl Command for DisableDebug { // 81 FE 01 00 DisEncrypt // 81 0D 01 0F ClearCodeFlashB // 81 0D 02 08 xx ClearCodeFlash +// 81 11 01 0D unkown in query info, before GetChipRomRamSplit #[cfg(test)] mod tests { diff --git a/src/flash_op.rs b/src/flash_op.rs index 38459ba..e2a7817 100644 --- a/src/flash_op.rs +++ b/src/flash_op.rs @@ -3,51 +3,34 @@ /// For both CH32V20X and CH32V30X // 5, 6 pub const CH32V307: [u8; 446] = [ - 0x01, 0x11, 0x02, 0xce, 0x93, 0x77, 0x15, 0x00, 0x99, 0xcf, - 0xb7, 0x06, 0x67, 0x45, 0xb7, 0x27, 0x02, 0x40, 0x93, 0x86, - 0x36, 0x12, 0x37, 0x97, 0xef, 0xcd, 0xd4, 0xc3, 0x13, 0x07, - 0xb7, 0x9a, 0xd8, 0xc3, 0xd4, 0xd3, 0xd8, 0xd3, 0x93, 0x77, - 0x25, 0x00, 0x95, 0xc7, 0xb7, 0x27, 0x02, 0x40, 0x98, 0x4b, - 0xad, 0x66, 0x37, 0x38, 0x00, 0x40, 0x13, 0x67, 0x47, 0x00, - 0x98, 0xcb, 0x98, 0x4b, 0x93, 0x86, 0xa6, 0xaa, 0x13, 0x67, - 0x07, 0x04, 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, 0x61, 0xeb, - 0x98, 0x4b, 0x6d, 0x9b, 0x98, 0xcb, 0x93, 0x77, 0x45, 0x00, - 0xa9, 0xcb, 0x93, 0x07, 0xf6, 0x0f, 0xa1, 0x83, 0x2e, 0xc6, - 0x2d, 0x68, 0x81, 0x76, 0x3e, 0xca, 0xb7, 0x08, 0x02, 0x00, - 0xb7, 0x27, 0x02, 0x40, 0x37, 0x33, 0x00, 0x40, 0x13, 0x08, - 0xa8, 0xaa, 0xfd, 0x16, 0x98, 0x4b, 0x33, 0x67, 0x17, 0x01, - 0x98, 0xcb, 0x32, 0x47, 0xd8, 0xcb, 0x98, 0x4b, 0x13, 0x67, - 0x07, 0x04, 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, 0x41, 0xeb, - 0x98, 0x4b, 0x75, 0x8f, 0x98, 0xcb, 0x32, 0x47, 0x13, 0x07, - 0x07, 0x10, 0x3a, 0xc6, 0x52, 0x47, 0x7d, 0x17, 0x3a, 0xca, - 0x69, 0xfb, 0x93, 0x77, 0x85, 0x00, 0xd5, 0xcb, 0x93, 0x07, - 0xf6, 0x0f, 0x2e, 0xc6, 0xa1, 0x83, 0x3e, 0xca, 0x37, 0x27, - 0x02, 0x40, 0x1c, 0x4b, 0xc1, 0x66, 0x41, 0x68, 0xd5, 0x8f, - 0x1c, 0xcb, 0xb7, 0x16, 0x00, 0x20, 0xb7, 0x27, 0x02, 0x40, - 0x93, 0x08, 0x00, 0x04, 0x37, 0x03, 0x20, 0x00, 0x98, 0x4b, - 0x33, 0x67, 0x07, 0x01, 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, - 0x75, 0xff, 0x32, 0x47, 0x3a, 0xc8, 0x46, 0xcc, 0x62, 0x47, - 0x0d, 0xef, 0x98, 0x4b, 0x33, 0x67, 0x67, 0x00, 0x98, 0xcb, - 0xd8, 0x47, 0x05, 0x8b, 0x75, 0xff, 0xd8, 0x47, 0x41, 0x8b, - 0x39, 0xc3, 0xd8, 0x47, 0xc1, 0x76, 0xfd, 0x16, 0x13, 0x67, - 0x07, 0x01, 0xd8, 0xc7, 0x98, 0x4b, 0x21, 0x45, 0x75, 0x8f, - 0x98, 0xcb, 0x05, 0x61, 0x02, 0x90, 0x23, 0x20, 0xd8, 0x00, - 0x25, 0xb7, 0x23, 0x20, 0x03, 0x01, 0xa5, 0xb7, 0x42, 0x47, - 0x13, 0x8e, 0x46, 0x00, 0x94, 0x42, 0x14, 0xc3, 0x42, 0x47, - 0x11, 0x07, 0x3a, 0xc8, 0x62, 0x47, 0x7d, 0x17, 0x3a, 0xcc, - 0xd8, 0x47, 0x09, 0x8b, 0x75, 0xff, 0xf2, 0x86, 0x5d, 0xb7, - 0x32, 0x47, 0x13, 0x07, 0x07, 0x10, 0x3a, 0xc6, 0x52, 0x47, - 0x7d, 0x17, 0x3a, 0xca, 0x49, 0xf3, 0x98, 0x4b, 0xc1, 0x76, - 0xfd, 0x16, 0x75, 0x8f, 0x98, 0xcb, 0x41, 0x89, 0x19, 0xe1, - 0x01, 0x45, 0x45, 0xbf, 0x2e, 0xc6, 0x0d, 0x06, 0x02, 0xca, - 0x09, 0x82, 0x32, 0xcc, 0xb7, 0x17, 0x00, 0x20, 0x98, 0x43, - 0x13, 0x86, 0x47, 0x00, 0xd2, 0x47, 0xb2, 0x46, 0x8a, 0x07, - 0xb6, 0x97, 0x9c, 0x43, 0x63, 0x18, 0xf7, 0x02, 0xd2, 0x47, - 0x32, 0x47, 0x8a, 0x07, 0xba, 0x97, 0x98, 0x43, 0xf2, 0x47, - 0xba, 0x97, 0x3e, 0xce, 0xd2, 0x47, 0x85, 0x07, 0x3e, 0xca, - 0xd2, 0x46, 0x62, 0x47, 0xb2, 0x87, 0xe3, 0xe8, 0xe6, 0xfc, - 0xb7, 0x27, 0x00, 0x20, 0x98, 0x4b, 0xf2, 0x47, 0xe3, 0x09, - 0xf7, 0xfa, 0x41, 0x45, 0xb9, 0xbf + 0x01, 0x11, 0x02, 0xce, 0x93, 0x77, 0x15, 0x00, 0x99, 0xcf, 0xb7, 0x06, 0x67, 0x45, 0xb7, 0x27, + 0x02, 0x40, 0x93, 0x86, 0x36, 0x12, 0x37, 0x97, 0xef, 0xcd, 0xd4, 0xc3, 0x13, 0x07, 0xb7, 0x9a, + 0xd8, 0xc3, 0xd4, 0xd3, 0xd8, 0xd3, 0x93, 0x77, 0x25, 0x00, 0x95, 0xc7, 0xb7, 0x27, 0x02, 0x40, + 0x98, 0x4b, 0xad, 0x66, 0x37, 0x38, 0x00, 0x40, 0x13, 0x67, 0x47, 0x00, 0x98, 0xcb, 0x98, 0x4b, + 0x93, 0x86, 0xa6, 0xaa, 0x13, 0x67, 0x07, 0x04, 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, 0x61, 0xeb, + 0x98, 0x4b, 0x6d, 0x9b, 0x98, 0xcb, 0x93, 0x77, 0x45, 0x00, 0xa9, 0xcb, 0x93, 0x07, 0xf6, 0x0f, + 0xa1, 0x83, 0x2e, 0xc6, 0x2d, 0x68, 0x81, 0x76, 0x3e, 0xca, 0xb7, 0x08, 0x02, 0x00, 0xb7, 0x27, + 0x02, 0x40, 0x37, 0x33, 0x00, 0x40, 0x13, 0x08, 0xa8, 0xaa, 0xfd, 0x16, 0x98, 0x4b, 0x33, 0x67, + 0x17, 0x01, 0x98, 0xcb, 0x32, 0x47, 0xd8, 0xcb, 0x98, 0x4b, 0x13, 0x67, 0x07, 0x04, 0x98, 0xcb, + 0xd8, 0x47, 0x05, 0x8b, 0x41, 0xeb, 0x98, 0x4b, 0x75, 0x8f, 0x98, 0xcb, 0x32, 0x47, 0x13, 0x07, + 0x07, 0x10, 0x3a, 0xc6, 0x52, 0x47, 0x7d, 0x17, 0x3a, 0xca, 0x69, 0xfb, 0x93, 0x77, 0x85, 0x00, + 0xd5, 0xcb, 0x93, 0x07, 0xf6, 0x0f, 0x2e, 0xc6, 0xa1, 0x83, 0x3e, 0xca, 0x37, 0x27, 0x02, 0x40, + 0x1c, 0x4b, 0xc1, 0x66, 0x41, 0x68, 0xd5, 0x8f, 0x1c, 0xcb, 0xb7, 0x16, 0x00, 0x20, 0xb7, 0x27, + 0x02, 0x40, 0x93, 0x08, 0x00, 0x04, 0x37, 0x03, 0x20, 0x00, 0x98, 0x4b, 0x33, 0x67, 0x07, 0x01, + 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, 0x75, 0xff, 0x32, 0x47, 0x3a, 0xc8, 0x46, 0xcc, 0x62, 0x47, + 0x0d, 0xef, 0x98, 0x4b, 0x33, 0x67, 0x67, 0x00, 0x98, 0xcb, 0xd8, 0x47, 0x05, 0x8b, 0x75, 0xff, + 0xd8, 0x47, 0x41, 0x8b, 0x39, 0xc3, 0xd8, 0x47, 0xc1, 0x76, 0xfd, 0x16, 0x13, 0x67, 0x07, 0x01, + 0xd8, 0xc7, 0x98, 0x4b, 0x21, 0x45, 0x75, 0x8f, 0x98, 0xcb, 0x05, 0x61, 0x02, 0x90, 0x23, 0x20, + 0xd8, 0x00, 0x25, 0xb7, 0x23, 0x20, 0x03, 0x01, 0xa5, 0xb7, 0x42, 0x47, 0x13, 0x8e, 0x46, 0x00, + 0x94, 0x42, 0x14, 0xc3, 0x42, 0x47, 0x11, 0x07, 0x3a, 0xc8, 0x62, 0x47, 0x7d, 0x17, 0x3a, 0xcc, + 0xd8, 0x47, 0x09, 0x8b, 0x75, 0xff, 0xf2, 0x86, 0x5d, 0xb7, 0x32, 0x47, 0x13, 0x07, 0x07, 0x10, + 0x3a, 0xc6, 0x52, 0x47, 0x7d, 0x17, 0x3a, 0xca, 0x49, 0xf3, 0x98, 0x4b, 0xc1, 0x76, 0xfd, 0x16, + 0x75, 0x8f, 0x98, 0xcb, 0x41, 0x89, 0x19, 0xe1, 0x01, 0x45, 0x45, 0xbf, 0x2e, 0xc6, 0x0d, 0x06, + 0x02, 0xca, 0x09, 0x82, 0x32, 0xcc, 0xb7, 0x17, 0x00, 0x20, 0x98, 0x43, 0x13, 0x86, 0x47, 0x00, + 0xd2, 0x47, 0xb2, 0x46, 0x8a, 0x07, 0xb6, 0x97, 0x9c, 0x43, 0x63, 0x18, 0xf7, 0x02, 0xd2, 0x47, + 0x32, 0x47, 0x8a, 0x07, 0xba, 0x97, 0x98, 0x43, 0xf2, 0x47, 0xba, 0x97, 0x3e, 0xce, 0xd2, 0x47, + 0x85, 0x07, 0x3e, 0xca, 0xd2, 0x46, 0x62, 0x47, 0xb2, 0x87, 0xe3, 0xe8, 0xe6, 0xfc, 0xb7, 0x27, + 0x00, 0x20, 0x98, 0x4b, 0xf2, 0x47, 0xe3, 0x09, 0xf7, 0xfa, 0x41, 0x45, 0xb9, 0xbf, ]; /// For CH32V103 diff --git a/src/lib.rs b/src/lib.rs index 845bcaa..f4b479e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,6 @@ pub enum RiscvChip { impl RiscvChip { /// Support flash protect commands, and info query commands pub fn support_flash_protect(&self) -> bool { - // type 3, 2, 7, 0x0A, 0x0b do not support write protect matches!( self, RiscvChip::CH32V103 @@ -121,6 +120,7 @@ impl RiscvChip { | RiscvChip::CH32V003 | RiscvChip::CH643 | RiscvChip::CH32L103 + | RiscvChip::CH32X035 ) } diff --git a/src/main.rs b/src/main.rs index a9ff17c..35116a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -197,8 +197,10 @@ fn main() -> Result<()> { log::info!("{dmstatus:#?}"); } Erase {} => { - log::info!("Erase Flash"); + log::info!("Erase Flash..."); probe.erase_flash()?; + log::debug!("Wait for some time to finish erase..."); + sleep(Duration::from_millis(1000)); } Flash { address, diff --git a/src/operations.rs b/src/operations.rs index 68c3989..3dc96b4 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -11,7 +11,7 @@ use crate::{ device::{ChipInfo, WchLink}, dmi::DebugModuleInterface, error::AbstractcsCmdErr, - regs::{self, Abstractcs, DMReg, Dmcontrol, Dmstatus}, + regs::{self, Abstractcs, Dmcontrol, Dmstatus}, transport::Transport, Error, Result, RiscvChip, }; @@ -149,11 +149,7 @@ impl WchLink { pub fn protect_flash(&mut self, protect: bool) -> Result<()> { // HACK: requires a fresh attach - self.send_command(commands::control::OptEnd)?; - - let probe_info = self.send_command(commands::control::GetProbeInfo)?; - - self.send_command(commands::control::AttachChip)?; + self.reattach_chip()?; let flash_protected_flag = self.send_command(commands::FlashProtect::CheckReadProtect)?; let protected = flash_protected_flag == commands::FlashProtect::FLAG_PROTECTED; @@ -166,15 +162,13 @@ impl WchLink { "unprotected" } ); - // - // return Ok(()); } - let use_v2 = probe_info.version() >= (2, 9); + let use_v2 = false; //probe_info.version() >= (2, 9); let cmd = match (protect, use_v2) { (true, true) => commands::FlashProtect::ProtectEx, - (false, true) => commands::FlashProtect::UnprotectEx, (true, false) => commands::FlashProtect::Protect, + (false, true) => commands::FlashProtect::UnprotectEx, (false, false) => commands::FlashProtect::Unprotect, }; @@ -204,6 +198,12 @@ impl WchLink { Ok(()) } + fn reattach_chip(&mut self) -> Result<()> { + self.detach_chip()?; + self.attach_chip(self.chip.as_ref().map(|i| i.chip_family))?; + Ok(()) + } + pub fn read_flash_size_kb(&mut self) -> Result { // Ref: (DS) Chapter 31 Electronic Signature (ESIG) let raw_flash_cap = self.read_memory(0x1FFFF7E0, 4)?; @@ -263,7 +263,7 @@ impl WchLink { .support_flash_protect() { let ret = self.send_command(commands::FlashProtect::CheckReadProtect)?; - if ret == 1 { + if ret == commands::FlashProtect::FLAG_PROTECTED { log::warn!("Flash is protected, unprotecting..."); self.protect_flash(false)?; } else if ret == 2 { @@ -272,7 +272,6 @@ impl WchLink { } } self.send_command(Program::EraseFlash)?; - self.send_command(control::AttachChip)?; Ok(()) } @@ -282,54 +281,65 @@ impl WchLink { let write_pack_size = self.chip.as_ref().unwrap().chip_family.write_pack_size(); let data_packet_size = self.chip.as_ref().unwrap().chip_family.data_packet_size(); - let mut data = data.to_vec(); - if data.len() % 256 != 0 { - data.resize((data.len() / 256 + 1) * 256, 0xFF); - } + let data = data.to_vec(); log::trace!("Using write pack size {}", write_pack_size); //if data.len() < write_pack_size as usize { // data.resize(write_pack_size as usize, 0xff); // } - // wlink_ready_write - self.send_command(Program::Prepare)?; - self.send_command(SetWriteMemoryRegion { - start_addr: address, - len: data.len() as _, - })?; + let mut retries = 0; + while retries < 3 { + // wlink_ready_write + self.send_command(Program::Prepare)?; + self.send_command(SetWriteMemoryRegion { + start_addr: address, + len: data.len() as _, + })?; - self.send_command(Program::WriteFlashOP)?; - // wlink_ramcodewrite - self.device_handle.write_data_endpoint( - self.chip.as_ref().unwrap().chip_family.flash_op(), - data_packet_size, - )?; + self.send_command(Program::WriteFlashOP)?; + // wlink_ramcodewrite + self.device_handle.write_data_endpoint( + self.chip.as_ref().unwrap().chip_family.flash_op(), + data_packet_size, + )?; - log::debug!("Flash op written"); + log::debug!("Flash OP written"); - if let Ok(n) = self.send_command(Program::Unknown07AfterFlashOPWritten) { - if n != 0x07 { - return Err(Error::Custom(format!( - "Unknown07AfterFlashOPWritten: {}", - n - ))); + std::thread::sleep(Duration::from_millis(10)); + if let Ok(n) = self.send_command(Program::Unknown07AfterFlashOPWritten) { + if n == 0x07 { + break; + } } + log::warn!("Unknown07AfterFlashOPWritten failed, retrying..."); + std::thread::sleep(Duration::from_millis(100)); + self.reattach_chip()?; + + retries += 1; + } + if retries >= 3 { + return Err(Error::Custom( + "Unknown07AfterFlashOPWritten failed".to_string(), + )); } // wlink_fastprogram self.send_command(Program::WriteFlash)?; - self.device_handle - .write_data_endpoint(&data, data_packet_size)?; + for chunk in data.chunks(write_pack_size as usize) { + self.device_handle + .write_data_endpoint(&chunk, data_packet_size)?; + } std::thread::sleep(Duration::from_secs(2)); let rxbuf = self.device_handle.read_data_endpoint(4)?; - println!("=> {rxbuf:02x?}"); - if rxbuf[3] != 0x02 && rxbuf[3] != 0x04 { + // 41 01 01 04 + if rxbuf[3] != 0x04 { return Err(Error::Custom(format!( // 0x05 // 0x18 - "Error while fastprogram: {:02x}", - rxbuf[3] + // 0xff + "Error while fastprogram: {:02x?}", + rxbuf ))); } diff --git a/src/transport.rs b/src/transport.rs index 471a6b6..c2f7077 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -4,7 +4,7 @@ use std::time::Duration; use rusb::DeviceHandle; -use crate::Result; +use crate::{Error, Result}; const ENDPOINT_OUT: u8 = 0x01; const ENDPOINT_IN: u8 = 0x81; @@ -66,26 +66,30 @@ impl Transport for DeviceHandle { return Err(crate::Error::InvalidPayloadLength); } log::trace!("read data ep {} bytes", bytes_read); - if bytes_read == 4 { - log::trace!("recv data {}", hex::encode(&buf)); + if bytes_read <= 10 { + log::trace!("recv data {}", hex::encode(&buf[..bytes_read])); } - Ok(buf) + if bytes_read != n { + log::warn!("read data ep {} bytes", bytes_read); + return Err(Error::InvalidPayloadLength); + } + Ok(buf[..n].to_vec()) } // pWriteData fn write_data_endpoint(&mut self, buf: &[u8], packet_len: usize) -> Result<()> { - let mut bytes_written = 0; - while bytes_written < buf.len() { - let chunk = &buf[bytes_written..(bytes_written + packet_len).min(buf.len())]; + for chunk in buf.chunks(packet_len) { + let mut chunk = chunk.to_vec(); + if chunk.len() < packet_len { + chunk.resize(packet_len, 0xff); + } self.write_bulk( RAW_ENDPOINT_OUT, - chunk, + &chunk, Duration::from_millis(USB_TIMEOUT_MS), )?; - bytes_written += chunk.len(); } - log::trace!("write data ep {} bytes", bytes_written); - + log::trace!("write data ep {} bytes", buf.len()); Ok(()) } }