Skip to content

Commit

Permalink
examples: add usbd-f072 demo
Browse files Browse the repository at this point in the history
  • Loading branch information
decaday committed Dec 26, 2024
1 parent e9ac3ac commit 6969a06
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 0 deletions.
13 changes: 13 additions & 0 deletions examples/usbd-f072/.cargo/config.toml
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"
55 changes: 55 additions & 0 deletions examples/usbd-f072/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[package]
name = "py32f072-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 # <-

13 changes: 13 additions & 0 deletions examples/usbd-f072/README.md
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).
10 changes: 10 additions & 0 deletions examples/usbd-f072/build.rs
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");
}
111 changes: 111 additions & 0 deletions examples/usbd-f072/src/bin/hid.rs
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));
}
}
}
}
}
89 changes: 89 additions & 0 deletions examples/usbd-f072/src/bin/serial.rs
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
}
}

0 comments on commit 6969a06

Please sign in to comment.