Send reset via software
This commit is contained in:
parent
5f41ee6bdf
commit
d7243aff99
4 changed files with 66 additions and 50 deletions
|
@ -20,6 +20,7 @@ use rp_pico as bsp;
|
||||||
use bsp::hal::{
|
use bsp::hal::{
|
||||||
clocks::{init_clocks_and_plls, Clock},
|
clocks::{init_clocks_and_plls, Clock},
|
||||||
pac,
|
pac,
|
||||||
|
rom_data::reset_to_usb_boot,
|
||||||
sio::Sio,
|
sio::Sio,
|
||||||
usb::UsbBus,
|
usb::UsbBus,
|
||||||
watchdog::Watchdog,
|
watchdog::Watchdog,
|
||||||
|
@ -30,7 +31,7 @@ use embedded_hal::adc::OneShot;
|
||||||
|
|
||||||
use usb_device::{class_prelude::*, prelude::*};
|
use usb_device::{class_prelude::*, prelude::*};
|
||||||
|
|
||||||
use crate::serial::Serial;
|
use crate::serial::{Commands, Serial};
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
|
@ -119,36 +120,11 @@ fn main() -> ! {
|
||||||
delay.delay_ms(8);
|
delay.delay_ms(8);
|
||||||
|
|
||||||
if usb_dev.poll(&mut [&mut serial]) {
|
if usb_dev.poll(&mut [&mut serial]) {
|
||||||
|
if let Some(command) = serial.read() {
|
||||||
// let mut buf = [0u8; 64];
|
match command {
|
||||||
|
Commands::Reset => reset_to_usb_boot(0, 0),
|
||||||
// match serial.read(&mut buf) {
|
}
|
||||||
// Err(_e) => {
|
}
|
||||||
// // Do nothing
|
|
||||||
// }
|
|
||||||
// Ok(0) => {
|
|
||||||
// // Do nothing
|
|
||||||
// }
|
|
||||||
// Ok(count) => {
|
|
||||||
// // Convert to upper case
|
|
||||||
// buf.iter_mut().take(count).for_each(|b| {
|
|
||||||
// b.make_ascii_uppercase();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Send back to the host
|
|
||||||
// let mut wr_ptr = &buf[..count];
|
|
||||||
|
|
||||||
// while !wr_ptr.is_empty() {
|
|
||||||
// match serial.write(wr_ptr) {
|
|
||||||
// Ok(len) => wr_ptr = &wr_ptr[len..],
|
|
||||||
// // On error, just drop unwritten data.
|
|
||||||
// // One possible error is Err(WouldBlock), meaning the USB
|
|
||||||
// // write buffer is full.
|
|
||||||
// Err(_) => break,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,20 @@ use usbd_serial::SerialPort;
|
||||||
|
|
||||||
use numtoa::NumToA;
|
use numtoa::NumToA;
|
||||||
|
|
||||||
|
pub enum Commands {
|
||||||
|
Reset,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Serial<'a> {
|
pub struct Serial<'a> {
|
||||||
serial: SerialPort<'a, UsbBus>,
|
serial: SerialPort<'a, UsbBus>,
|
||||||
buf: [u8; 20],
|
buf: [u8; 256],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Serial<'a> {
|
impl<'a> Serial<'a> {
|
||||||
pub fn new(usb_bus: &'a UsbBusAllocator<UsbBus>) -> Self {
|
pub fn new(usb_bus: &'a UsbBusAllocator<UsbBus>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
serial: SerialPort::new(&usb_bus),
|
serial: SerialPort::new(&usb_bus),
|
||||||
buf: [0u8; 20],
|
buf: [0u8; 256],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +40,22 @@ impl<'a> Serial<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self) -> Option<Commands> {
|
||||||
|
match self.serial.read(&mut self.buf) {
|
||||||
|
Err(_e) => None,
|
||||||
|
Ok(0) => None,
|
||||||
|
Ok(count) => {
|
||||||
|
let c = count.min(self.buf.len());
|
||||||
|
let msg = &self.buf[..c];
|
||||||
|
|
||||||
|
match msg {
|
||||||
|
b"reset" => Some(Commands::Reset),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> usb_device::class::UsbClass<rp_pico::hal::usb::UsbBus> for Serial<'a> {
|
impl<'a> usb_device::class::UsbClass<rp_pico::hal::usb::UsbBus> for Serial<'a> {
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::{
|
||||||
use std::sync::atomic::Ordering::SeqCst;
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering::SeqCst},
|
||||||
|
Mutex,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
use gtk::{prelude::*, PolicyType, TextView};
|
use gtk::{prelude::*, PolicyType, TextView};
|
||||||
use gtk::{Application, ApplicationWindow};
|
use gtk::{Application, ApplicationWindow};
|
||||||
|
@ -12,7 +17,7 @@ mod port;
|
||||||
use port::*;
|
use port::*;
|
||||||
|
|
||||||
static CONNECTED: AtomicBool = AtomicBool::new(false);
|
static CONNECTED: AtomicBool = AtomicBool::new(false);
|
||||||
static mut PORT: Option<Port> = None;
|
static PORT: Mutex<Option<Port>> = Mutex::new(None);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = Application::builder()
|
let app = Application::builder()
|
||||||
|
@ -33,6 +38,7 @@ fn main() {
|
||||||
let pid = Entry::builder().text("0x27dd").editable(true).build();
|
let pid = Entry::builder().text("0x27dd").editable(true).build();
|
||||||
let vid = Entry::builder().text("0x16c0").editable(true).build();
|
let vid = Entry::builder().text("0x16c0").editable(true).build();
|
||||||
let connect_button = Button::with_label("Connect");
|
let connect_button = Button::with_label("Connect");
|
||||||
|
let reset_button = Button::with_label("Reset");
|
||||||
let serial_info = TextView::new();
|
let serial_info = TextView::new();
|
||||||
let scrolled_window = ScrolledWindow::builder()
|
let scrolled_window = ScrolledWindow::builder()
|
||||||
.vscrollbar_policy(PolicyType::Automatic)
|
.vscrollbar_policy(PolicyType::Automatic)
|
||||||
|
@ -40,6 +46,7 @@ fn main() {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
top_bar_box.pack_end(&connect_button, true, true, 3);
|
top_bar_box.pack_end(&connect_button, true, true, 3);
|
||||||
|
top_bar_box.pack_end(&reset_button, true, true, 3);
|
||||||
top_bar_box.pack_end(&vid, true, true, 3);
|
top_bar_box.pack_end(&vid, true, true, 3);
|
||||||
top_bar_box.pack_end(&pid, true, true, 3);
|
top_bar_box.pack_end(&pid, true, true, 3);
|
||||||
|
|
||||||
|
@ -51,8 +58,9 @@ fn main() {
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
// loop forever
|
// loop forever
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
let mut port_lock = PORT.lock().unwrap();
|
||||||
if let Some(port) = &mut PORT {
|
|
||||||
|
if let Some(port) = &mut *port_lock {
|
||||||
// handle incoming message
|
// handle incoming message
|
||||||
match port.read().unwrap() {
|
match port.read().unwrap() {
|
||||||
SerialReadResult::Message(msg) => {
|
SerialReadResult::Message(msg) => {
|
||||||
|
@ -64,7 +72,8 @@ fn main() {
|
||||||
SerialReadResult::Timeout => (),
|
SerialReadResult::Timeout => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
thread::sleep(Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,10 +104,22 @@ fn main() {
|
||||||
if let Ok(port) = Port::open(usb_id, serialport_settings) {
|
if let Ok(port) = Port::open(usb_id, serialport_settings) {
|
||||||
CONNECTED.store(true, SeqCst);
|
CONNECTED.store(true, SeqCst);
|
||||||
|
|
||||||
unsafe {
|
*PORT.lock().unwrap() = Some(port);
|
||||||
PORT = Some(port);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
reset_button.connect_clicked(move |_| {
|
||||||
|
if CONNECTED.load(SeqCst) {
|
||||||
|
CONNECTED.store(false, SeqCst);
|
||||||
|
|
||||||
|
let mut port_lock = PORT.lock().unwrap();
|
||||||
|
|
||||||
|
if let Some(port) = &mut *port_lock {
|
||||||
|
port.write("reset").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
*port_lock = None;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ impl Port {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn write(&mut self, msg: &str) -> Result<()> {
|
pub fn write(&mut self, msg: &str) -> Result<()> {
|
||||||
self.serial_port
|
self.serial_port
|
||||||
.write(msg.as_bytes())
|
.write(msg.as_bytes())
|
||||||
|
|
Loading…
Reference in a new issue