USB test that works! It parrots.

I mostly just wanted to save this state of the project
This commit is contained in:
2026-08-15 19:01:34 -05:00
parent 53e9faa2ab
commit dc935d56ee
4 changed files with 159 additions and 20 deletions
Generated
+19
View File
@@ -588,6 +588,8 @@ dependencies = [
"embedded-io-async 0.7.0",
"heapless 0.9.3",
"panic-probe",
"static_cell",
"usb_communication_shared",
]
[[package]]
@@ -1319,6 +1321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
@@ -1418,6 +1421,15 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "static_cell"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
dependencies = [
"portable-atomic",
]
[[package]]
name = "string_cache"
version = "0.8.9"
@@ -1600,6 +1612,13 @@ dependencies = [
"portable-atomic",
]
[[package]]
name = "usb_communication_shared"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "usbd-hid"
version = "0.10.1"
+2
View File
@@ -20,3 +20,5 @@ heapless = "0.9"
embedded-hal-async = "1.0"
embedded-io-async = { version = "0.7.0", features = ["defmt"] }
defmt-rtt = "1.3.0"
static_cell = "2.1.1"
usb_communication_shared = { version = "0.1.0", path = "../usb_communication_shared" }
+32 -13
View File
@@ -4,29 +4,34 @@
use defmt::*;
use defmt_rtt as _;
use embassy_executor::Spawner;
use embassy_rp::{
bind_interrupts,
peripherals::USB,
usb::{Driver as UsbDriver, InterruptHandler as UsbInterruptHandler},
};
use embassy_time::Timer;
use panic_probe as _;
// Program metadata for `picotool info`.
// This isn't needed, but it's recommended to have these minimal entries.
#[unsafe(link_section = ".bi_entries")]
#[used]
pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [
embassy_rp::binary_info::rp_program_name!(c"Blinky Example"),
embassy_rp::binary_info::rp_program_description!(
c"This example tests the RP Pico on board LED, connected to gpio 25"
),
embassy_rp::binary_info::rp_cargo_version!(),
embassy_rp::binary_info::rp_program_build_attribute!(),
];
use crate::usb::handle_usb;
mod usb;
bind_interrupts!(struct Irqs{
USBCTRL_IRQ => UsbInterruptHandler<USB>;
});
#[embassy_executor::main(
executor = "embassy_rp::executor::Executor",
entry = "cortex_m_rt::entry"
)]
async fn main(_spawner: Spawner) {
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let usb_driver = UsbDriver::new(p.USB, Irqs);
spawner.spawn(handle_usb(usb_driver).unwrap());
let led_future = async {
loop {
info!("led on!");
Timer::after_millis(500).await;
@@ -34,4 +39,18 @@ async fn main(_spawner: Spawner) {
info!("led off!");
Timer::after_millis(500).await;
}
};
led_future.await;
}
// Program metadata for `picotool info`.
// This isn't needed, but it's recommended to have these minimal entries.
#[unsafe(link_section = ".bi_entries")]
#[used]
pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [
embassy_rp::binary_info::rp_program_name!(c"USB-Communication"),
embassy_rp::binary_info::rp_program_description!(c"USB-Communication System"),
embassy_rp::binary_info::rp_cargo_version!(),
embassy_rp::binary_info::rp_program_build_attribute!(),
];
+99
View File
@@ -0,0 +1,99 @@
use defmt::*;
use heapless::Vec;
use static_cell::StaticCell;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel};
use embassy_rp::{peripherals::USB, usb::Driver as UsbDriver};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State as UsbState};
use usb_communication_shared::request::Packet as RequestPacket;
use usb_communication_shared::response::Packet as ResponsePacket;
static USB_SEND_CHANNEL: Channel<CriticalSectionRawMutex, ResponsePacket, 4> = Channel::new();
static USB_RECIEVE_CHANNEL: Channel<CriticalSectionRawMutex, RequestPacket, 4> = Channel::new();
#[embassy_executor::task]
pub async fn handle_usb(usb_driver: UsbDriver<'static, USB>) {
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
config.manufacturer = Some("Melfely");
config.product = Some("USB-Parrot");
config.serial_number = Some("1234");
config.max_power = 100;
config.max_packet_size_0 = 64;
let mut usb_builder = {
static CONFIG_DESCRIPTOR: StaticCell<[u8; 256]> = StaticCell::new();
static BOS_DESCRIPTOR: StaticCell<[u8; 256]> = StaticCell::new();
static CONTROL_BUF: StaticCell<[u8; 64]> = StaticCell::new();
let embassy = embassy_usb::Builder::new(
usb_driver,
config,
CONFIG_DESCRIPTOR.init([0; 256]),
BOS_DESCRIPTOR.init([0; 256]),
&mut [],
CONTROL_BUF.init([0; 64]),
);
embassy
};
let usb_class = {
static STATE: StaticCell<UsbState> = StaticCell::new();
let state = STATE.init(UsbState::new());
CdcAcmClass::new(&mut usb_builder, state, 64)
};
let (mut usb_tx, mut usb_rx, _usb_control) = usb_class.split_with_control();
let mut usb = usb_builder.build();
let usb_fut = usb.run();
let channel = Channel::<CriticalSectionRawMutex, Vec<u8, 64>, 4>::new();
let mut usb_buf = [0; 64];
let usb_rx_future = async {
let sender = channel.sender();
loop {
usb_rx.wait_connection().await;
info!("USB RX Connected");
loop {
match usb_rx.read_packet(&mut usb_buf).await {
Err(e) => {
error!(
"Usb read error: {:?}. Assume Discconection",
Debug2Format(&e)
);
break;
}
Ok(_) => {
let vec: Vec<u8, 64> = usb_buf.into();
sender.send(vec).await;
}
}
}
}
};
let usb_tx_future = async {
let reciever = channel.receiver();
loop {
usb_tx.wait_connection().await;
info!("USB TX Connected");
loop {
let packet = reciever.receive().await;
match usb_tx.write_packet(&packet).await {
Ok(_) => {}
Err(err) => {
error!(
"Usb write error: {:?}, Assume Disconnection",
Debug2Format(&err)
);
break;
}
}
}
}
};
embassy_futures::join::join3(usb_fut, usb_rx_future, usb_tx_future).await;
}