Added some stuff for the monitor (can already reboot the target)
This commit is contained in:
45
Cargo.lock
generated
45
Cargo.lock
generated
@@ -65,12 +65,29 @@ version = "0.2.175"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.5"
|
version = "2.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numtoa"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pbr"
|
name = "pbr"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@@ -112,6 +129,21 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_termios"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serial2"
|
name = "serial2"
|
||||||
version = "0.2.32"
|
version = "0.2.32"
|
||||||
@@ -134,6 +166,18 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termion"
|
||||||
|
version = "4.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"libredox",
|
||||||
|
"numtoa",
|
||||||
|
"redox_termios",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tulflash"
|
name = "tulflash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -141,6 +185,7 @@ dependencies = [
|
|||||||
"argp",
|
"argp",
|
||||||
"pbr",
|
"pbr",
|
||||||
"serial2",
|
"serial2",
|
||||||
|
"termion",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@@ -7,3 +7,4 @@ edition = "2024"
|
|||||||
argp = "0.4.0"
|
argp = "0.4.0"
|
||||||
pbr = "1.1.1"
|
pbr = "1.1.1"
|
||||||
serial2 = "0.2.32"
|
serial2 = "0.2.32"
|
||||||
|
termion = "4.0.5"
|
||||||
|
@@ -22,7 +22,8 @@ pub struct Args {
|
|||||||
pub enum ArgCommand {
|
pub enum ArgCommand {
|
||||||
Read(ArgRead),
|
Read(ArgRead),
|
||||||
Write(ArgWrite),
|
Write(ArgWrite),
|
||||||
Erase(ArgErase)
|
Erase(ArgErase),
|
||||||
|
Monitor(ArgMonitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs)]
|
#[derive(FromArgs)]
|
||||||
@@ -80,6 +81,11 @@ pub struct ArgWrite {
|
|||||||
#[argp(subcommand, name = "erase")]
|
#[argp(subcommand, name = "erase")]
|
||||||
pub struct ArgErase {}
|
pub struct ArgErase {}
|
||||||
|
|
||||||
|
#[derive(FromArgs)]
|
||||||
|
#[argp(description = "Opens the serial monitor.")]
|
||||||
|
#[argp(subcommand, name = "monitor")]
|
||||||
|
pub struct ArgMonitor {}
|
||||||
|
|
||||||
pub fn parse() -> Args {
|
pub fn parse() -> Args {
|
||||||
let args: Args = argp::parse_args_or_exit(argp::DEFAULT);
|
let args: Args = argp::parse_args_or_exit(argp::DEFAULT);
|
||||||
args
|
args
|
||||||
|
13
src/main.rs
13
src/main.rs
@@ -9,6 +9,9 @@ use args::*;
|
|||||||
mod ihex;
|
mod ihex;
|
||||||
use ihex::{IntelHexWriter, IntelHexReader, DataRecord};
|
use ihex::{IntelHexWriter, IntelHexReader, DataRecord};
|
||||||
|
|
||||||
|
mod monitor;
|
||||||
|
use monitor::Monitor;
|
||||||
|
|
||||||
mod target;
|
mod target;
|
||||||
use target::{PhysicalTarget, Target};
|
use target::{PhysicalTarget, Target};
|
||||||
|
|
||||||
@@ -201,6 +204,13 @@ fn erase_chip(_args: ArgErase, target: &mut PhysicalTarget) -> Result<(), Error>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn monitor_chip(_args: ArgMonitor, target: &mut PhysicalTarget) -> Result<(), Error> {
|
||||||
|
let _ = Monitor::new().run(target.port())?;
|
||||||
|
target.resync_target().unwrap();
|
||||||
|
target.read_info(0x00, 0x00).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = args::parse();
|
let args = args::parse();
|
||||||
|
|
||||||
@@ -211,7 +221,8 @@ fn main() {
|
|||||||
let res = match args.command {
|
let res = match args.command {
|
||||||
ArgCommand::Read(args) => read_chip(args, &mut target),
|
ArgCommand::Read(args) => read_chip(args, &mut target),
|
||||||
ArgCommand::Write(args) => write_chip(args, &mut target),
|
ArgCommand::Write(args) => write_chip(args, &mut target),
|
||||||
ArgCommand::Erase(args) => erase_chip(args, &mut target)
|
ArgCommand::Erase(args) => erase_chip(args, &mut target),
|
||||||
|
ArgCommand::Monitor(args) => monitor_chip(args, &mut target)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
|
76
src/monitor.rs
Normal file
76
src/monitor.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
use std::io::Error;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use serial2::SerialPort;
|
||||||
|
|
||||||
|
use termion::raw::IntoRawMode;
|
||||||
|
use termion::event::Key;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
|
||||||
|
pub struct Monitor {
|
||||||
|
hooks: Vec<(Key, &'static str)>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Monitor {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut hooks = Vec::new();
|
||||||
|
|
||||||
|
hooks.push((Key::Ctrl('c'), "Exit monitor"));
|
||||||
|
hooks.push((Key::Ctrl('r'), "Reboot target"));
|
||||||
|
|
||||||
|
Self { hooks }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_hook(&mut self, key: Key, desc: &'static str) {
|
||||||
|
self.hooks.push((key, desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self, port: &mut SerialPort) -> Result<Key, Error> {
|
||||||
|
port.set_dtr(true)?;
|
||||||
|
port.set_rts(true)?;
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
port.set_dtr(false)?;
|
||||||
|
port.set_rts(false)?;
|
||||||
|
|
||||||
|
println!("Monitor controls:");
|
||||||
|
|
||||||
|
for (key, desc) in &self.hooks {
|
||||||
|
let key = match key {
|
||||||
|
Key::Char(c) => format!("{}", c.to_uppercase()),
|
||||||
|
Key::Ctrl(c) => format!("Ctrl+{}", c.to_uppercase()),
|
||||||
|
key => format!("{:?}", key)
|
||||||
|
};
|
||||||
|
|
||||||
|
println!(" {} - {}", key, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let mut _stdout = std::io::stdout().into_raw_mode().unwrap();
|
||||||
|
|
||||||
|
let mut stdin = termion::async_stdin().keys();
|
||||||
|
|
||||||
|
'main: loop {
|
||||||
|
if let Some(Ok(key)) = stdin.next() {
|
||||||
|
if let Key::Ctrl('r') = key {
|
||||||
|
port.set_dtr(true)?;
|
||||||
|
port.set_rts(true)?;
|
||||||
|
std::thread::sleep(Duration::from_millis(10));
|
||||||
|
port.set_dtr(false)?;
|
||||||
|
port.set_rts(false)?;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hook_key, _) in &self.hooks {
|
||||||
|
if hook_key == &key {
|
||||||
|
break 'main Ok(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{:?}\r", key);
|
||||||
|
} else {
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -22,24 +22,10 @@ impl PhysicalTarget {
|
|||||||
|
|
||||||
port.set_read_timeout(Duration::from_millis(100))?;
|
port.set_read_timeout(Duration::from_millis(100))?;
|
||||||
|
|
||||||
port.set_dtr(false)?;
|
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
|
||||||
|
|
||||||
for i in (0..5).rev() {
|
|
||||||
port.write(b"U")?;
|
|
||||||
|
|
||||||
let mut buf = [0u8; 1];
|
|
||||||
port.read(&mut buf)?;
|
|
||||||
|
|
||||||
if buf[0] == b'U' { break }
|
|
||||||
|
|
||||||
if i == 0 {
|
|
||||||
Err(Error::other(format!("Invalid sync response: 0x{:02X}", buf[0])))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new = Self { port };
|
let mut new = Self { port };
|
||||||
|
|
||||||
|
new.resync_target()?;
|
||||||
|
|
||||||
let manufacturer = new.read_info(0x00, 0x00).unwrap();
|
let manufacturer = new.read_info(0x00, 0x00).unwrap();
|
||||||
let family = new.read_info(0x00, 0x01).unwrap();
|
let family = new.read_info(0x00, 0x01).unwrap();
|
||||||
let name = new.read_info(0x00, 0x02).unwrap();
|
let name = new.read_info(0x00, 0x02).unwrap();
|
||||||
@@ -50,6 +36,29 @@ impl PhysicalTarget {
|
|||||||
Ok(new)
|
Ok(new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resync_target(&mut self) -> Result<(), Error> {
|
||||||
|
self.port.set_dtr(true)?;
|
||||||
|
self.port.set_rts(true)?;
|
||||||
|
std::thread::sleep(Duration::from_millis(10));
|
||||||
|
self.port.set_dtr(false)?;
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
|
||||||
|
for i in (0..5).rev() {
|
||||||
|
self.port.write(b"U")?;
|
||||||
|
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
self.port.read(&mut buf)?;
|
||||||
|
|
||||||
|
if buf[0] == b'U' { break }
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
Err(Error::other(format!("Invalid sync response: 0x{:02X}", buf[0])))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_info(&mut self, category: u8, idx: u8) -> Result<u8, Error> {
|
pub fn read_info(&mut self, category: u8, idx: u8) -> Result<u8, Error> {
|
||||||
self.send_command(0x05, 0, &[category, idx])?;
|
self.send_command(0x05, 0, &[category, idx])?;
|
||||||
|
|
||||||
@@ -126,6 +135,10 @@ impl PhysicalTarget {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn port(&mut self) -> &mut SerialPort {
|
||||||
|
&mut self.port
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Target for PhysicalTarget {
|
impl Target for PhysicalTarget {
|
||||||
@@ -228,7 +241,11 @@ impl Target for PhysicalTarget {
|
|||||||
|
|
||||||
impl Drop for PhysicalTarget {
|
impl Drop for PhysicalTarget {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.port.set_dtr(true);
|
self.port.set_dtr(true).unwrap();
|
||||||
|
self.port.set_rts(true).unwrap();
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
self.port.set_dtr(false).unwrap();
|
||||||
|
self.port.set_rts(false).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user