pub mod chips;
pub mod commands;
pub mod dmi;
pub mod error;
pub mod firmware;
pub mod flash_op;
pub mod operations;
pub mod probe;
pub mod regs;
pub mod usb_device;
use clap::{builder::PossibleValue, ValueEnum};
use probe::WchLink;
pub use crate::error::{Error, Result};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum RiscvChip {
CH32V103 = 0x01,
CH57X = 0x02,
CH56X = 0x03,
CH32V20X = 0x05,
CH32V30X = 0x06,
CH582 = 0x07,
CH32V003 = 0x09,
CH8571 = 0x0A, CH59X = 0x0B, CH643 = 0x0C, CH32X035 = 0x0D, CH32L103 = 0x0E, CH641 = 0x49,
CH585 = 0x4B,
CH564 = 0x0F,
CH32V007 = 0x4E,
CH645 = 0x46,
CH32V317 = 0x86,
CH32F10X = 0x04,
CH32F20X = 0x08,
}
impl ValueEnum for RiscvChip {
fn value_variants<'a>() -> &'a [Self] {
&[
RiscvChip::CH32V103,
RiscvChip::CH57X,
RiscvChip::CH56X,
RiscvChip::CH32V20X,
RiscvChip::CH32V30X,
RiscvChip::CH582,
RiscvChip::CH32V003,
RiscvChip::CH8571,
RiscvChip::CH59X,
RiscvChip::CH643,
RiscvChip::CH32X035,
RiscvChip::CH32L103,
RiscvChip::CH641,
RiscvChip::CH585,
RiscvChip::CH564,
RiscvChip::CH32V007,
RiscvChip::CH645,
RiscvChip::CH32V317,
]
}
fn to_possible_value(&self) -> Option<PossibleValue> {
match self {
RiscvChip::CH32V103 => Some(PossibleValue::new("CH32V103")),
RiscvChip::CH57X => Some(PossibleValue::new("CH57X")),
RiscvChip::CH56X => Some(PossibleValue::new("CH56X")),
RiscvChip::CH32V20X => Some(PossibleValue::new("CH32V20X")),
RiscvChip::CH32V30X => Some(PossibleValue::new("CH32V30X")),
RiscvChip::CH582 => Some(PossibleValue::new("CH582")),
RiscvChip::CH585 => Some(PossibleValue::new("CH585")),
RiscvChip::CH32V003 => Some(PossibleValue::new("CH32V003")),
RiscvChip::CH8571 => Some(PossibleValue::new("CH8571")),
RiscvChip::CH59X => Some(PossibleValue::new("CH59X")),
RiscvChip::CH643 => Some(PossibleValue::new("CH643")),
RiscvChip::CH32X035 => Some(PossibleValue::new("CH32X035")),
RiscvChip::CH32L103 => Some(PossibleValue::new("CH32L103")),
RiscvChip::CH641 => Some(PossibleValue::new("CH641")),
RiscvChip::CH564 => Some(PossibleValue::new("CH564")),
RiscvChip::CH32V007 => Some(PossibleValue::new("CH32V007")),
RiscvChip::CH645 => Some(PossibleValue::new("CH645")),
RiscvChip::CH32V317 => Some(PossibleValue::new("CH32V317")),
_ => None,
}
}
fn from_str(input: &str, ignore_case: bool) -> std::result::Result<Self, String> {
let s = if ignore_case {
input.to_ascii_uppercase()
} else {
input.to_string()
};
match &*s {
"CH32V103" => Ok(RiscvChip::CH32V103),
"CH32V20X" | "CH32V203" | "CH32V208" => Ok(RiscvChip::CH32V20X),
"CH32V30X" | "CH32V303" | "CH32V305" | "CH32V307" => Ok(RiscvChip::CH32V30X),
"CH32V317" => Ok(RiscvChip::CH32V317),
"CH32V003" => Ok(RiscvChip::CH32V003),
"CH32L103" => Ok(RiscvChip::CH32L103),
"CH32X0" | "CH32X03X" | "CH32X033" | "CH32X034" | "CH32X035" => Ok(RiscvChip::CH32X035),
"CH32V002" | "CH32V004" | "CH32V005" | "CH32V006" | "CH32V007" | "CH32M007" => {
Ok(RiscvChip::CH32V007)
}
"CH565" | "CH569" => Ok(RiscvChip::CH56X),
"CH57X" | "CH571" | "CH573" => Ok(RiscvChip::CH57X),
"CH581" | "CH582" | "CH583" => Ok(RiscvChip::CH582),
"CH584" | "CH585" => Ok(RiscvChip::CH585),
"CH564" => Ok(RiscvChip::CH564),
"CH59X" | "CH591" | "CH592" => Ok(RiscvChip::CH59X),
"CH641" => Ok(RiscvChip::CH641),
"CH643" => Ok(RiscvChip::CH643),
"CH645" | "CH653" => Ok(RiscvChip::CH645),
"CH8571" => Ok(RiscvChip::CH8571),
"CH56X" => {
log::warn!(
"Ambiguous chip family, assume CH569. use either CH564, CH565 or CH569 instead"
);
Ok(RiscvChip::CH56X)
}
"CH58X" => {
log::warn!(
"Ambiguous chip family, assume CH582. use either CH582 or CH585 instead"
);
Ok(RiscvChip::CH582)
}
_ => Err(format!("Unknown chip: {}", s)),
}
}
}
impl RiscvChip {
pub fn support_flash_protect(&self) -> bool {
matches!(
self,
RiscvChip::CH32V103
| RiscvChip::CH32V20X
| RiscvChip::CH32V30X
| RiscvChip::CH32V003
| RiscvChip::CH32V007
| RiscvChip::CH32L103
| RiscvChip::CH32X035
| RiscvChip::CH641
| RiscvChip::CH645
| RiscvChip::CH32V317
)
}
pub(crate) fn support_ram_rom_mode(&self) -> bool {
matches!(
self,
RiscvChip::CH32V20X | RiscvChip::CH32V30X | RiscvChip::CH32V317
)
}
pub fn support_query_info(&self) -> bool {
!matches!(
self,
RiscvChip::CH57X
| RiscvChip::CH56X
| RiscvChip::CH582
| RiscvChip::CH585
| RiscvChip::CH59X
)
}
pub fn support_disable_debug(&self) -> bool {
matches!(
self,
RiscvChip::CH57X
| RiscvChip::CH56X
| RiscvChip::CH582
| RiscvChip::CH585
| RiscvChip::CH59X
)
}
pub fn support_special_erase(&self) -> bool {
!matches!(
self,
RiscvChip::CH57X
| RiscvChip::CH56X
| RiscvChip::CH582
| RiscvChip::CH585
| RiscvChip::CH59X
)
}
pub fn support_sdi_print(&self) -> bool {
matches!(
self,
RiscvChip::CH32V003
| RiscvChip::CH645
| RiscvChip::CH32V007
| RiscvChip::CH32V103
| RiscvChip::CH32V20X
| RiscvChip::CH32V30X
| RiscvChip::CH32X035
| RiscvChip::CH32L103
| RiscvChip::CH643
| RiscvChip::CH641
| RiscvChip::CH32V317
)
}
pub fn is_rv32ec(&self) -> bool {
matches!(
self,
RiscvChip::CH32V003 | RiscvChip::CH641 | RiscvChip::CH32V007
)
}
pub fn reset_command(&self) -> crate::commands::Reset {
match self {
RiscvChip::CH57X | RiscvChip::CH582 | RiscvChip::CH59X => crate::commands::Reset::Chip,
_ => crate::commands::Reset::Normal,
}
}
pub fn do_post_init(&self, probe: &mut WchLink) -> Result<()> {
match self {
RiscvChip::CH32V103 => {
let _ = probe.send_command(commands::RawCommand::<0x0d>(vec![0x03]))?;
}
RiscvChip::CH32V30X | RiscvChip::CH8571 | RiscvChip::CH32V003 => {
}
RiscvChip::CH57X | RiscvChip::CH582 => {
log::warn!("The debug interface has been opened, there is a risk of code leakage.");
log::warn!("Please ensure that the debug interface has been closed before leaving factory!");
}
RiscvChip::CH56X => {
log::warn!("The debug interface has been opened, there is a risk of code leakage.");
log::warn!("Please ensure that the debug interface has been closed before leaving factory!");
let resp = probe.send_command(commands::RawCommand::<0x0d>(vec![0x04]))?;
log::debug!("TODO, handle CH56X resp {:?}", resp);
}
_ => (),
}
Ok(())
}
fn get_flash_op(&self) -> &'static [u8] {
match self {
RiscvChip::CH32V003 | RiscvChip::CH641 => &flash_op::CH32V003,
RiscvChip::CH32V103 => &flash_op::CH32V103,
RiscvChip::CH32V20X | RiscvChip::CH32V30X => &flash_op::CH32V307,
RiscvChip::CH56X => &flash_op::CH569,
RiscvChip::CH57X => &flash_op::CH573,
RiscvChip::CH582 | RiscvChip::CH59X | RiscvChip::CH585 => &flash_op::CH583,
RiscvChip::CH8571 => &flash_op::OP8571,
RiscvChip::CH32X035 | RiscvChip::CH643 => &flash_op::CH643,
RiscvChip::CH32L103 => &flash_op::CH32L103,
RiscvChip::CH564 => &flash_op::CH564,
RiscvChip::CH32V007 => &flash_op::CH32V007,
RiscvChip::CH645 => &flash_op::CH645,
RiscvChip::CH32V317 => &flash_op::CH32V317,
RiscvChip::CH32F10X => todo!(),
RiscvChip::CH32F20X => todo!(),
}
}
fn try_from_u8(value: u8) -> Result<Self> {
match value {
0x01 => Ok(RiscvChip::CH32V103),
0x02 => Ok(RiscvChip::CH57X),
0x03 => Ok(RiscvChip::CH56X),
0x05 => Ok(RiscvChip::CH32V20X),
0x06 => Ok(RiscvChip::CH32V30X),
0x07 => Ok(RiscvChip::CH582),
0x09 => Ok(RiscvChip::CH32V003),
0x0A => Ok(RiscvChip::CH8571),
0x0B => Ok(RiscvChip::CH59X),
0x0C => Ok(RiscvChip::CH643),
0x0D => Ok(RiscvChip::CH32X035),
0x0E => Ok(RiscvChip::CH32L103),
0x49 => Ok(RiscvChip::CH641),
0x4B => Ok(RiscvChip::CH585),
0x0F => Ok(RiscvChip::CH564),
0x4E => Ok(RiscvChip::CH32V007),
0x46 => Ok(RiscvChip::CH645),
0x86 => Ok(RiscvChip::CH32V317),
0x04 => Ok(RiscvChip::CH32F10X),
0x08 => Ok(RiscvChip::CH32F20X),
_ => Err(Error::UnknownChip(value)),
}
}
pub fn data_packet_size(&self) -> usize {
match self {
RiscvChip::CH32V103 => 128,
RiscvChip::CH32V003 | RiscvChip::CH641 => 64,
_ => 256,
}
}
pub fn code_flash_start(&self) -> u32 {
match self {
RiscvChip::CH56X
| RiscvChip::CH57X
| RiscvChip::CH582
| RiscvChip::CH585
| RiscvChip::CH59X
| RiscvChip::CH8571 => 0x0000_0000,
_ => 0x0800_0000,
}
}
pub fn fix_code_flash_start(&self, start_address: u32) -> u32 {
let addr = self.code_flash_start() + start_address;
if addr >= 0x10000000 {
addr - 0x08000000
} else {
addr
}
}
pub fn write_pack_size(&self) -> u32 {
match self {
RiscvChip::CH32V003 | RiscvChip::CH641 | RiscvChip::CH32V007 => 1024,
_ => 4096,
}
}
}