From ad30077abef982dba837d4f4b651bb2f971805d6 Mon Sep 17 00:00:00 2001 From: Andelf Date: Sun, 5 Nov 2023 00:01:01 +0800 Subject: [PATCH] feat: impl serial watch --- CHANGELOG.md | 4 ++ Cargo.lock | 145 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 ++ src/device.rs | 4 +- src/error.rs | 4 ++ src/lib.rs | 2 +- src/main.rs | 12 +++- src/operations.rs | 37 ++++++++++++ 8 files changed, 207 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f943d..25cacc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `--watch-serial` for `flash` subcommand + ### Changed - No erase by default when flashing diff --git a/Cargo.lock b/Cargo.lock index 6f45396..afdca8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,36 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "CoreFoundation-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b" +dependencies = [ + "libc", + "mach", +] + +[[package]] +name = "IOKit-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a" +dependencies = [ + "CoreFoundation-sys", + "libc", + "mach", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.4" @@ -62,6 +92,18 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" + [[package]] name = "cc" version = "1.0.83" @@ -209,6 +251,26 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libudev" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0" +dependencies = [ + "libc", + "libudev-sys", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "libusb1-sys" version = "0.6.4" @@ -227,12 +289,41 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "mach" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" +dependencies = [ + "libc", +] + +[[package]] +name = "mach2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -311,6 +402,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "rusb" version = "0.9.3" @@ -321,6 +441,12 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.190" @@ -341,6 +467,24 @@ dependencies = [ "syn", ] +[[package]] +name = "serialport" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c32634e2bd4311420caa504404a55fad2131292c485c97014cbed89a5899885f" +dependencies = [ + "CoreFoundation-sys", + "IOKit-sys", + "bitflags 2.0.2", + "cfg-if", + "libudev", + "mach2", + "nix", + "regex", + "scopeguard", + "winapi", +] + [[package]] name = "simplelog" version = "0.12.1" @@ -630,6 +774,7 @@ dependencies = [ "nu-pretty-hex", "object", "rusb", + "serialport", "simplelog", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 8fce24d..4767ca3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ keywords = ["embedded", "WCH", "CH32V", "WCH-Link"] readme = "README.md" license = "MIT/Apache-2.0" +[features] +default = [] + [dependencies] anyhow = "1.0.68" bitfield = "0.14.0" @@ -29,3 +32,4 @@ object = { version = "0.32", default-features = false, features = [ "std", ] } indicatif = "0.17.7" +serialport = { version = "4.2.2" } diff --git a/src/device.rs b/src/device.rs index 3ec7b8f..64db155 100644 --- a/src/device.rs +++ b/src/device.rs @@ -9,8 +9,8 @@ use crate::{ Result, RiscvChip, }; -const VENDOR_ID: u16 = 0x1a86; -const PRODUCT_ID: u16 = 0x8010; +pub const VENDOR_ID: u16 = 0x1a86; +pub const PRODUCT_ID: u16 = 0x8010; const ENDPOINT_OUT: u8 = 0x01; const ENDPOINT_IN: u8 = 0x81; diff --git a/src/error.rs b/src/error.rs index 887e1fd..35dd372 100644 --- a/src/error.rs +++ b/src/error.rs @@ -39,6 +39,10 @@ pub enum Error { DmiFailed, #[error("Operation timeout")] Timeout, + #[error("Serial port error: {0}")] + Serial(#[from] serialport::Error), + #[error("Io error: {0}")] + Io(#[from] std::io::Error), } #[derive(Debug, Clone, Copy)] diff --git a/src/lib.rs b/src/lib.rs index d12036f..223bbce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ pub mod dmi; pub mod error; pub mod flash_op; pub mod format; -mod operations; +pub mod operations; pub mod regs; pub mod transport; diff --git a/src/main.rs b/src/main.rs index efb4b20..163005e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,6 +79,9 @@ enum Commands { /// Enable SDI print after reset #[arg(long, default_value = "false")] enable_sdi_print: bool, + /// Open serial port(print only) after reset + #[arg(long, default_value = "false")] + watch_serial: bool, /// Path to the firmware file to flash path: String, }, @@ -310,6 +313,7 @@ fn main() -> Result<()> { no_run, path, enable_sdi_print, + watch_serial, } => { probe.dump_info(false)?; @@ -339,9 +343,13 @@ fn main() -> Result<()> { if enable_sdi_print { probe.enable_sdi_print(true)?; will_detach = false; - log::info!("Now you can connect to the WCH-Link serial port"); + log::info!("Now connect to the WCH-Link serial port to read SDI print"); + } + if watch_serial { + wlink::operations::watch_serial()?; + } else { + sleep(Duration::from_millis(500)); } - sleep(Duration::from_millis(500)); } } Unprotect {} => { diff --git a/src/operations.rs b/src/operations.rs index df93943..0a7ae8f 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -696,3 +696,40 @@ fn parse_misa(misa: u32) -> Option { } Some(s) } + +/// SDI print +pub fn watch_serial() -> Result<()> { + use serialport::SerialPortType; + + let port_info = serialport::available_ports()? + .into_iter() + .find(|port| { + if let SerialPortType::UsbPort(info) = &port.port_type { + info.vid == crate::device::VENDOR_ID && info.pid == crate::device::PRODUCT_ID + } else { + false + } + }) + .ok_or_else(|| Error::Custom("No serial port found".to_string()))?; + log::debug!("Opening serial port: {:?}", port_info.port_name); + + let mut port = serialport::new(&port_info.port_name, 115200) + .timeout(Duration::from_millis(1000)) + .open()?; + + log::trace!("Serial port opened: {:?}", port); + + loop { + let mut buf = [0u8; 1024]; + match port.read(&mut buf) { + Ok(n) => { + if n > 0 { + let s = String::from_utf8_lossy(&buf[..n]); + print!("{}", s); + } + } + Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => (), + Err(e) => return Err(e.into()), + } + } +}