Skip to content

Commit

Permalink
Extra USB serial with menu kind of works
Browse files Browse the repository at this point in the history
Need to figure out echo problem
  • Loading branch information
mkj committed May 23, 2023
1 parent b801592 commit 58461b6
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 39 deletions.
2 changes: 2 additions & 0 deletions embassy/demos/picow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ embassy-usb-driver = { git = "https://github.com/embassy-rs/embassy", rev = "3e7
embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" }
embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "3e730aa8b06401003202bf9e21a9c83ec6b21b0e" }

# embedded-io = { path = "/home/matt/3rd/rs/embedded-io" }

[profile.dev]
debug = 2
debug-assertions = true
Expand Down
39 changes: 25 additions & 14 deletions embassy/demos/picow/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ pub use defmt::{debug, info, warn, panic, error, trace};

use {defmt_rtt as _, panic_probe as _};

use core::fmt::Write as _;


use embassy_executor::Spawner;
use embassy_net::Stack;
use embassy_futures::join::join;
use embassy_futures::select::select;
use embassy_rp::{pio::PioPeripheral, interrupt};
use embassy_rp::peripherals::FLASH;
use embedded_io::{asynch, Io};
use embedded_io::asynch::Write;
use embedded_io::asynch::Write as _;

use heapless::{String, Vec};

Expand Down Expand Up @@ -79,10 +82,6 @@ async fn main(spawner: Spawner) {
SunsetMutex::new(config)
);

let usb_pipe = singleton!(takepipe::TakePipe::new());
let usb_pipe = singleton!(usb_pipe.base());
let usb_irq = interrupt::take!(USBCTRL_IRQ);
spawner.spawn(usb_serial_task(p.USB, usb_irq, usb_pipe)).unwrap();

let (wifi_net, wifi_pw) = {
let c = config.lock().await;
Expand All @@ -96,6 +95,9 @@ async fn main(spawner: Spawner) {
let wifi_control = singleton!(SunsetMutex::new(wifi_control));
spawner.spawn(net_task(&stack)).unwrap();

let usb_pipe = singleton!(takepipe::TakePipe::new());
let usb_pipe = singleton!(usb_pipe.base());

let state = GlobalState {
usb_pipe,
wifi_control,
Expand All @@ -104,6 +106,9 @@ async fn main(spawner: Spawner) {
};
let state = singleton!(state);

let usb_irq = interrupt::take!(USBCTRL_IRQ);
spawner.spawn(usb_serial_task(p.USB, usb_irq, state)).unwrap();

for _ in 0..NUM_LISTENERS {
spawner.spawn(listener(&stack, config, state)).unwrap();
}
Expand Down Expand Up @@ -135,7 +140,9 @@ struct DemoShell {
username: SunsetMutex<String<20>>,
}

// `local` is set for usb serial menus which require different auth
async fn menu<R, W>(mut chanr: R, mut chanw: W,
local: bool,
state: &'static GlobalState) -> Result<()>
where R: asynch::Read+Io<Error=sunset::Error>,
W: asynch::Write+Io<Error=sunset::Error> {
Expand Down Expand Up @@ -163,9 +170,14 @@ async fn menu<R, W>(mut chanr: R, mut chanw: W,

// TODO: move this to a function or something
if menu.context.switch_usb1 {
serial(chanr, chanw, state).await?;
// TODO we could return to the menu on serial error?
break 'io;
menu.context.switch_usb1 = false;
if local {
writeln!(menu.context.out, "serial can't loop");
} else {
serial(chanr, chanw, state).await?;
// TODO we could return to the menu on serial error?
break 'io;
}
}

if menu.context.need_save {
Expand All @@ -178,6 +190,8 @@ async fn menu<R, W>(mut chanr: R, mut chanw: W,
warn!("Error writing flash");
}
}

menu.context.out.flush(&mut chanw).await?;
}
}
Ok(())
Expand Down Expand Up @@ -264,7 +278,7 @@ impl Shell for DemoShell {
if *self.username.lock().await == "serial" {
serial(stdio.clone(), stdio, self.ctx).await
} else {
menu(stdio.clone(), stdio, self.ctx).await
menu(stdio.clone(), stdio, false, self.ctx).await
}
};

Expand All @@ -280,13 +294,10 @@ async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! {
#[embassy_executor::task]
async fn usb_serial_task(usb: embassy_rp::peripherals::USB,
irq: embassy_rp::interrupt::USBCTRL_IRQ,
pipe: &'static TakeBase<'static>,
global: &'static GlobalState,
) -> ! {

info!("usb serial");
let (mut rx, mut tx) = pipe.split();

usbserial::usb_serial(usb, irq, &mut tx, &mut rx).await;
usbserial::usb_serial(usb, irq, global).await;
todo!("shoudln't exit");
}

66 changes: 42 additions & 24 deletions embassy/demos/picow/src/usbserial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use log::{debug, error, info, log, trace, warn};
#[cfg(feature = "defmt")]
pub use defmt::{debug, error, info, panic, trace, warn};

use embassy_futures::join::join;
use embassy_futures::join::{join, join3};
use embassy_rp::usb::Instance;
use embassy_usb::class::cdc_acm::{self, CdcAcmClass, State};
use embassy_usb::Builder;
Expand All @@ -17,16 +17,15 @@ use embedded_io::{asynch, Io, asynch::BufRead};
use heapless::Vec;

use sunset::*;
use sunset_embassy::io_copy;
use sunset_embassy::*;

pub async fn usb_serial<R, W>(
use crate::*;

pub(crate) async fn usb_serial(
usb: embassy_rp::peripherals::USB,
irq: embassy_rp::interrupt::USBCTRL_IRQ,
tx: &mut W,
rx: &mut R,
global: &'static GlobalState,
)
where R: asynch::Read+Io<Error=sunset::Error>,
W: asynch::Write+Io<Error=sunset::Error>
{
info!("usb_serial top");

Expand All @@ -53,7 +52,9 @@ pub async fn usb_serial<R, W>(
let mut bos_descriptor = [0; 256];
let mut control_buf = [0; 64];

let mut state = State::new();
// lives longer than builder
let mut usb_state0 = State::new();
let mut usb_state2 = State::new();

let mut builder = Builder::new(
driver,
Expand All @@ -64,34 +65,54 @@ pub async fn usb_serial<R, W>(
&mut control_buf,
);

let cdc = CdcAcmClass::new(&mut builder, &mut state, 64);
let (mut cdc_tx, mut cdc_rx) = cdc.split();
// let cdc_tx = &mut cdc_tx;
// let cdc_rx = &mut cdc_rx;
// if00
let cdc0 = CdcAcmClass::new(&mut builder, &mut usb_state0, 64);
let (mut cdc0_tx, mut cdc0_rx) = cdc0.split();
// if02
let cdc2 = CdcAcmClass::new(&mut builder, &mut usb_state2, 64);
let (mut cdc2_tx, mut cdc2_rx) = cdc2.split();

let mut usb = builder.build();


// Run the USB device.
let usb_fut = usb.run();

let io = async {
let io0 = async {
let (mut chan_rx, mut chan_tx) = global.usb_pipe.split();
let chan_rx = &mut chan_rx;
let chan_tx = &mut chan_tx;
loop {
info!("usb waiting");
cdc0_rx.wait_connection().await;
info!("Connected");
let mut cdc0_tx = CDCWrite::new(&mut cdc0_tx);
let mut cdc0_rx = CDCRead::new(&mut cdc0_rx);

let io_tx = io_buf_copy(&mut cdc0_rx, chan_tx);
let io_rx = io_copy::<64, _, _>(chan_rx, &mut cdc0_tx);

let _ = join(io_rx, io_tx).await;
info!("Disconnected");
}
};

let setup = async {
loop {
info!("usb waiting");
cdc_rx.wait_connection().await;
cdc2_rx.wait_connection().await;
info!("Connected");
let mut cdc_tx = CDCWrite::new(&mut cdc_tx);
let mut cdc_rx = CDCRead::new(&mut cdc_rx);
let cdc2_tx = CDCWrite::new(&mut cdc2_tx);
let cdc2_rx = CDCRead::new(&mut cdc2_rx);

let io_tx = io_copy::<64, _, _>(&mut cdc_rx, tx);
let io_rx = io_copy::<64, _, _>(rx, &mut cdc_tx);
let _ = menu(cdc2_rx, cdc2_tx, true, global).await;

join(io_rx, io_tx).await;
info!("Disconnected");
}
};

info!("usb join");
join(usb_fut, io).await;
join3(usb_fut, io0, setup).await;
}

pub struct CDCRead<'a, 'p, D: Driver<'a>> {
Expand Down Expand Up @@ -184,10 +205,7 @@ impl<'a, D: Driver<'a>> asynch::Write for CDCWrite<'a, '_, D> {
async fn write(&mut self, buf: &[u8]) -> sunset::Result<usize> {
// limit to 63 so we can ignore dealing with ZLPs for now
let b = &buf[..buf.len().min(63)];
self.0
.write_packet(b)
.await
.map_err(|_| sunset::Error::ChannelEOF)?;
self.0.write_packet(b).await.map_err(|_| sunset::Error::ChannelEOF)?;
Ok(b.len())
}
}
Expand Down
17 changes: 17 additions & 0 deletions embassy/src/embassy_sunset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,20 @@ pub async fn io_copy<const B: usize, R, W>(r: &mut R, w: &mut W) -> Result<()>
#[allow(unreachable_code)]
Ok::<_, Error>(())
}

pub async fn io_buf_copy<R, W>(r: &mut R, w: &mut W) -> Result<()>
where R: asynch::BufRead+Io<Error=sunset::Error>,
W: asynch::Write+Io<Error=sunset::Error>
{
loop {
let b = r.fill_buf().await?;
if b.len() == 0 {
return sunset::error::ChannelEOF.fail();
}
let n = b.len();
w.write_all(b).await?;
r.consume(n)
}
#[allow(unreachable_code)]
Ok::<_, Error>(())
}
2 changes: 1 addition & 1 deletion embassy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ pub use client::SSHClient;

pub use embassy_channel::{ChanInOut, ChanIn, ChanOut};

pub use embassy_sunset::{SunsetMutex, SunsetRawMutex, io_copy};
pub use embassy_sunset::{SunsetMutex, SunsetRawMutex, io_copy, io_buf_copy};

0 comments on commit 58461b6

Please sign in to comment.