Skip to content

Commit

Permalink
chore: ch32x035 verfied
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Oct 2, 2023
1 parent d4b6b61 commit d483b23
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 101 deletions.
8 changes: 6 additions & 2 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
73 changes: 28 additions & 45 deletions src/flash_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -121,6 +120,7 @@ impl RiscvChip {
| RiscvChip::CH32V003
| RiscvChip::CH643
| RiscvChip::CH32L103
| RiscvChip::CH32X035
)
}

Expand Down
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
92 changes: 51 additions & 41 deletions src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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;
Expand All @@ -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,
};

Expand Down Expand Up @@ -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<u32> {
// Ref: (DS) Chapter 31 Electronic Signature (ESIG)
let raw_flash_cap = self.read_memory(0x1FFFF7E0, 4)?;
Expand Down Expand Up @@ -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 {
Expand All @@ -272,7 +272,6 @@ impl WchLink {
}
}
self.send_command(Program::EraseFlash)?;

self.send_command(control::AttachChip)?;
Ok(())
}
Expand All @@ -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
)));
}

Expand Down
26 changes: 15 additions & 11 deletions src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -66,26 +66,30 @@ impl Transport for DeviceHandle<rusb::Context> {
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(())
}
}

0 comments on commit d483b23

Please sign in to comment.