-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from decaday/feat/usbd
`usb-device` impl and example
- Loading branch information
Showing
10 changed files
with
348 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
# TODO(2) replace `$CHIP` with your chip's name (see `probe-rs chip list` output) | ||
runner = "probe-rs run --chip PY32F072xB" | ||
|
||
# rustflags = [ | ||
# "-C", "linker=flip-link", | ||
# ] | ||
|
||
[build] | ||
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ | ||
|
||
[env] | ||
DEFMT_LOG = "trace" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
[package] | ||
name = "py32f072-usbd-examples" | ||
version = "0.2.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
panic-halt = "1.0.0" | ||
cortex-m = { version = "0.7.7", features = [ | ||
"critical-section-single-core", | ||
"critical-section", | ||
] } | ||
cortex-m-rt = "0.7.3" | ||
cortex-m-semihosting = { version = "0.5" } | ||
panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
|
||
py32-hal = { path = "../../", default-features = false,features = [ "py32f072c1b", | ||
"time-driver-tim15", | ||
"defmt", | ||
"rt", | ||
"memory-x", | ||
"usb-device-impl", | ||
"embassy" | ||
]} | ||
|
||
defmt = "0.3" | ||
defmt-rtt = "0.4" | ||
embassy-futures = "0.1.1" | ||
embassy-usb = { version = "0.3.0", features = [ "defmt"]} | ||
usbd-human-interface-device = { version = "0.5.0", features = [ "defmt"]} | ||
|
||
portable-atomic = { version = "1.5", features = ["critical-section"] } | ||
static_cell = "2.1" | ||
usbd-serial = "0.2.2" | ||
usb-device = "0.3.2" | ||
|
||
|
||
# cargo build/run | ||
[profile.dev] | ||
codegen-units = 1 | ||
debug = 2 | ||
debug-assertions = true # <- | ||
incremental = false | ||
opt-level = 'z' # <- | ||
overflow-checks = true # <- | ||
|
||
# cargo build/run --release | ||
[profile.release] | ||
codegen-units = 1 | ||
debug = 2 | ||
debug-assertions = false # <- | ||
incremental = false | ||
lto = 'fat' | ||
opt-level = 3 # <- | ||
overflow-checks = false # <- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# `usb-device` (`usbd`) Demo | ||
|
||
> [!WARNING] | ||
> | ||
> This demo is intended to showcase the [usb-device](https://crates.io/crates/usb-device) crate, not the [embassy-usb](https://crates.io/crates/embassy-usb) crate. | ||
> | ||
> If you're looking for examples of USB async drivers, please refer to the [py32f072 examples](https://chatgpt.com/py32f072/src/bin). | ||
## Usage | ||
|
||
You need to enable the `usb-device-impl` feature and disable the `embassy-usb-driver-impl` feature. | ||
|
||
The PY32 uses a stripped-down version of the MUSB IP. For more information, check out the [musb](https://crates.io/crates/musb) crate. It includes implementations of both [embassy-usb-driver](https://crates.io/crates/embassy-usb-driver) and [usb-device](https://crates.io/crates/usb-device). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
fn main() { | ||
// `--nmagic` is required if memory section addresses are not aligned to 0x10000, | ||
// for example the FLASH and RAM sections in your `memory.x`. | ||
// See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 | ||
println!("cargo:rustc-link-arg=--nmagic"); | ||
|
||
println!("cargo:rustc-link-arg=-Tlink.x"); | ||
|
||
println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
#![no_std] | ||
#![no_main] | ||
#![feature(impl_trait_in_assoc_type)] | ||
|
||
use defmt::*; | ||
use py32_hal::bind_interrupts; | ||
use py32_hal::gpio::{Input, Level, Output, Pull, Speed}; | ||
use py32_hal::rcc::{Pll, PllMul, PllSource, Sysclk}; | ||
use py32_hal::time::Hertz; | ||
use py32_hal::usb::{self, InterruptHandler}; | ||
use {defmt_rtt as _, panic_probe as _}; | ||
|
||
use usb_device::{class_prelude::*, prelude::*}; | ||
use usbd_human_interface_device::page::Keyboard; | ||
use usbd_human_interface_device::prelude::*; | ||
|
||
bind_interrupts!(struct Irqs { | ||
USB => InterruptHandler<py32_hal::peripherals::USB>; | ||
}); | ||
|
||
#[cortex_m_rt::entry] | ||
fn main() -> ! { | ||
let mut cfg: py32_hal::Config = Default::default(); | ||
|
||
// PY32 USB uses PLL as the clock source and can only run at 48Mhz. | ||
cfg.rcc.hsi = Some(Hertz::mhz(16)); | ||
cfg.rcc.pll = Some(Pll { | ||
src: PllSource::HSI, | ||
mul: PllMul::MUL3, | ||
}); | ||
cfg.rcc.sys = Sysclk::PLL; | ||
let p = py32_hal::init(cfg); | ||
|
||
let mut led = Output::new(p.PB2, Level::High, Speed::Low); | ||
let button = Input::new(p.PB0, Pull::Up); | ||
|
||
let usb_bus = usb::new_bus(p.USB, Irqs, p.PA12, p.PA11); | ||
|
||
let usb_bus_allocator = UsbBusAllocator::new(usb_bus); | ||
|
||
let mut keyboard = UsbHidClassBuilder::new() | ||
.add_device(usbd_human_interface_device::device::keyboard::BootKeyboardConfig::default()) | ||
.build(&usb_bus_allocator); | ||
|
||
//https://pid.codes | ||
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus_allocator, UsbVidPid(0x1209, 0x0001)) | ||
.strings(&[StringDescriptors::default() | ||
.manufacturer("py32-rs team") | ||
.product("Boot Keyboard") | ||
.serial_number("TEST")]) | ||
.unwrap() | ||
.build(); | ||
|
||
let mut button_pressed = false; | ||
|
||
loop { | ||
if button.is_high() { | ||
if button_pressed { | ||
// Button was just released | ||
button_pressed = false; | ||
// Send release report with no keys pressed | ||
match keyboard.device().write_report([Keyboard::NoEventIndicated]) { | ||
Err(UsbHidError::WouldBlock) => {} | ||
Err(UsbHidError::Duplicate) => {} | ||
Ok(_) => {} | ||
Err(e) => { | ||
core::panic!("Failed to write keyboard report: {:?}", e) | ||
} | ||
}; | ||
} | ||
} else { | ||
if !button_pressed { | ||
// Button was just pressed | ||
button_pressed = true; | ||
info!("Button pressed"); | ||
// Send press report with 'A' key | ||
match keyboard.device().write_report([Keyboard::A]) { | ||
Err(UsbHidError::WouldBlock) => {} | ||
Err(UsbHidError::Duplicate) => {} | ||
Ok(_) => {} | ||
Err(e) => { | ||
core::panic!("Failed to write keyboard report: {:?}", e) | ||
} | ||
}; | ||
} | ||
} | ||
|
||
//Tick once per ms | ||
match keyboard.tick() { | ||
Err(UsbHidError::WouldBlock) => {} | ||
Ok(_) => {} | ||
Err(e) => { | ||
core::panic!("Failed to process keyboard tick: {:?}", e) | ||
} | ||
}; | ||
|
||
if usb_dev.poll(&mut [&mut keyboard]) { | ||
match keyboard.device().read_report() { | ||
Err(UsbError::WouldBlock) => { | ||
//do nothing | ||
} | ||
Err(e) => { | ||
core::panic!("Failed to read keyboard report: {:?}", e) | ||
} | ||
Ok(leds) => { | ||
led.set_level(Level::from(leds.caps_lock)); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
#![no_std] | ||
#![no_main] | ||
#![feature(impl_trait_in_assoc_type)] | ||
|
||
use defmt::*; | ||
use py32_hal::bind_interrupts; | ||
use py32_hal::gpio::{Level, Output, Speed}; | ||
use py32_hal::rcc::{Pll, PllMul, PllSource, Sysclk}; | ||
use py32_hal::time::Hertz; | ||
use py32_hal::usb::{self, InterruptHandler}; | ||
use {defmt_rtt as _, panic_probe as _}; | ||
|
||
use usb_device::{class_prelude::*, prelude::*}; | ||
use usbd_serial::{SerialPort, USB_CLASS_CDC}; | ||
|
||
bind_interrupts!(struct Irqs { | ||
USB => InterruptHandler<py32_hal::peripherals::USB>; | ||
}); | ||
|
||
#[cortex_m_rt::entry] | ||
fn main() -> ! { | ||
let mut cfg: py32_hal::Config = Default::default(); | ||
|
||
// PY32 USB uses PLL as the clock source and can only run at 48Mhz. | ||
cfg.rcc.hsi = Some(Hertz::mhz(16)); | ||
cfg.rcc.pll = Some(Pll { | ||
src: PllSource::HSI, | ||
mul: PllMul::MUL3, | ||
}); | ||
cfg.rcc.sys = Sysclk::PLL; | ||
let p = py32_hal::init(cfg); | ||
|
||
let mut led = Output::new(p.PB2, Level::High, Speed::Low); | ||
|
||
let usb_bus = usb::new_bus(p.USB, Irqs, p.PA12, p.PA11); | ||
|
||
let usb_bus_allocator = UsbBusAllocator::new(usb_bus); | ||
|
||
let mut serial = SerialPort::new(&usb_bus_allocator); | ||
|
||
let string_descriptors = StringDescriptors::new(LangID::EN_US) | ||
.manufacturer("py32-rs team") | ||
.product("Serial") | ||
.serial_number("TEST"); | ||
|
||
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus_allocator, UsbVidPid(0x16c0, 0x27dd)) | ||
.strings(&[string_descriptors]) | ||
.unwrap() | ||
.max_packet_size_0(64) | ||
.unwrap() | ||
.device_class(USB_CLASS_CDC) | ||
.build(); | ||
|
||
loop { | ||
if !usb_dev.poll(&mut [&mut serial]) { | ||
continue; | ||
} | ||
|
||
let mut buf = [0u8; 64]; | ||
|
||
match serial.read(&mut buf) { | ||
Ok(count) if count > 0 => { | ||
led.set_high(); // Turn on | ||
|
||
info!("data: {:x}", &buf[0..count]); | ||
|
||
// Echo back in upper case | ||
for c in buf[0..count].iter_mut() { | ||
if 0x61 <= *c && *c <= 0x7a { | ||
*c &= !0x20; | ||
} | ||
} | ||
|
||
let mut write_offset = 0; | ||
while write_offset < count { | ||
match serial.write(&buf[write_offset..count]) { | ||
Ok(len) if len > 0 => { | ||
write_offset += len; | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
_ => {} | ||
} | ||
|
||
led.set_low(); // Turn off | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.