Skip to content

Commit f30f325

Browse files
committed
Add nrf-usbd crate
1 parent ff39f42 commit f30f325

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+16390
-54
lines changed

.cargo/config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
3+
[build]
4+
target = "thumbv7em-none-eabi"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

Cargo.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[workspace]
2+
members = [
3+
".",
4+
"example",
5+
]
6+
7+
[package]
8+
name = "nrf-usbd"
9+
version = "0.1.0"
10+
edition = "2018"
11+
12+
13+
[dependencies]
14+
cortex-m = "0.7.2"
15+
usb-device = "0.2.8"
16+
vcell = "0.1.3"
17+
18+
[profile.dev]
19+
codegen-units = 1
20+
debug = 2
21+
debug-assertions = true
22+
incremental = false
23+
opt-level = 1
24+
overflow-checks = true
25+
26+
[profile.release]
27+
codegen-units = 1
28+
debug = 2
29+
debug-assertions = false
30+
incremental = false
31+
lto = "fat"
32+
opt-level = 's'
33+
overflow-checks = false
34+
35+
# do not optimize proc-macro crates = faster builds from scratch
36+
[profile.dev.build-override]
37+
codegen-units = 8
38+
debug = false
39+
debug-assertions = false
40+
opt-level = 0
41+
overflow-checks = false
42+
43+
[profile.release.build-override]
44+
codegen-units = 8
45+
debug = false
46+
debug-assertions = false
47+
opt-level = 0
48+
overflow-checks = false

example/.cargo/config

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2+
runner = "probe-run --chip nRF52840_xxAA"
3+
4+
rustflags = [
5+
"-C", "link-arg=--nmagic",
6+
"-C", "link-arg=-Tlink.x",
7+
"-C", "link-arg=-Tdefmt.x",
8+
]
9+
10+
[build]
11+
target = "thumbv7em-none-eabi"

example/Cargo.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "nrf-usbd-example"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[features]
7+
default = [
8+
"defmt-default",
9+
]
10+
defmt-default = []
11+
defmt-trace = []
12+
defmt-debug = []
13+
defmt-info = []
14+
defmt-warn = []
15+
defmt-error = []
16+
17+
[dependencies]
18+
panic-probe = { version = "0.2.0", features = ["print-defmt"] }
19+
defmt = "0.2.0"
20+
defmt-rtt = "0.2.0"
21+
22+
cortex-m = "0.7.2"
23+
cortex-m-rt = "0.6.12"
24+
25+
nrf-usbd = { path = "../" }
26+
usb-device = "0.2.7"
27+
usbd-serial = "0.1.0"
28+
nrf52840-pac = "0.9.0"
29+

example/build.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//! This build script copies the `memory.x` file from the crate root into
2+
//! a directory where the linker can always find it at build time.
3+
//! For many projects this is optional, as the linker always searches the
4+
//! project root directory -- wherever `Cargo.toml` is. However, if you
5+
//! are using a workspace or have a more complicated build setup, this
6+
//! build script becomes required. Additionally, by requesting that
7+
//! Cargo re-run the build script whenever `memory.x` is changed,
8+
//! updating `memory.x` ensures a rebuild of the application with the
9+
//! new memory settings.
10+
11+
use std::env;
12+
use std::fs::File;
13+
use std::io::Write;
14+
use std::path::PathBuf;
15+
16+
fn main() {
17+
// Put `memory.x` in our output directory and ensure it's
18+
// on the linker search path.
19+
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20+
File::create(out.join("memory.x"))
21+
.unwrap()
22+
.write_all(include_bytes!("memory.x"))
23+
.unwrap();
24+
println!("cargo:rustc-link-search={}", out.display());
25+
26+
// By default, Cargo will re-run a build script whenever
27+
// any file in the project changes. By specifying `memory.x`
28+
// here, we ensure the build script is only re-run when
29+
// `memory.x` is changed.
30+
println!("cargo:rerun-if-changed=memory.x");
31+
}

example/memory.x

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
MEMORY
2+
{
3+
/* NOTE 1 K = 1 KiBi = 1024 bytes */
4+
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
5+
RAM : ORIGIN = 0x20000000, LENGTH = 256K
6+
}

example/src/main.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use defmt_rtt as _;
5+
use nrf_usbd::{UsbPeripheral, Usbd};
6+
// global logger
7+
use panic_probe as _;
8+
9+
use core::str;
10+
use core::sync::atomic::{AtomicUsize, Ordering};
11+
use cortex_m_rt::entry;
12+
use defmt::*;
13+
use nrf52840_pac as pac;
14+
use usb_device::device::{UsbDeviceBuilder, UsbVidPid};
15+
use usbd_serial::{SerialPort, USB_CLASS_CDC};
16+
17+
defmt::timestamp! {"{=u64}", {
18+
static COUNT: AtomicUsize = AtomicUsize::new(0);
19+
// NOTE(no-CAS) `timestamps` runs with interrupts disabled
20+
let n = COUNT.load(Ordering::Relaxed);
21+
COUNT.store(n + 1, Ordering::Relaxed);
22+
n as u64
23+
}
24+
}
25+
26+
#[entry]
27+
fn main() -> ! {
28+
let p = pac::Peripherals::take().unwrap();
29+
30+
info!("Enabling ext hfosc...");
31+
p.CLOCK.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
32+
while p.CLOCK.events_hfclkstarted.read().bits() != 1 {}
33+
34+
info!("Waiting for vbus...");
35+
while !p.POWER.usbregstatus.read().vbusdetect().is_vbus_present() {}
36+
37+
//info!("Waiting for usbpwr...");
38+
//// wait until USB 3.3V supply is stable
39+
//while !p.POWER.events_usbpwrrdy.read().events_usbpwrrdy().bit() {}
40+
41+
info!("starting...");
42+
43+
let usb_bus = Usbd::new(Peripheral);
44+
let mut serial = SerialPort::new(&usb_bus);
45+
46+
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
47+
.product("nRF52840 Serial Port Demo")
48+
.device_class(USB_CLASS_CDC)
49+
.max_packet_size_0(64) // (makes control transfers 8x faster)
50+
.build();
51+
52+
info!("started!");
53+
54+
loop {
55+
if !usb_dev.poll(&mut [&mut serial]) {
56+
continue;
57+
}
58+
59+
let mut buf = [0u8; 64];
60+
61+
match serial.read(&mut buf) {
62+
Ok(count) if count > 0 => {
63+
let mut buf = &mut buf[..count];
64+
65+
info!("read: {=str}", unsafe { str::from_utf8_unchecked(buf) });
66+
67+
// Echo back in upper case
68+
for c in buf.iter_mut() {
69+
if 0x61 <= *c && *c <= 0x7a {
70+
*c &= !0x20;
71+
}
72+
}
73+
74+
info!("writing: {=str}", unsafe { str::from_utf8_unchecked(buf) });
75+
while !buf.is_empty() {
76+
match serial.write(buf) {
77+
Ok(len) => buf = &mut buf[len..],
78+
_ => {}
79+
}
80+
}
81+
82+
info!("write done")
83+
}
84+
_ => {}
85+
}
86+
}
87+
}
88+
89+
struct Peripheral;
90+
unsafe impl UsbPeripheral for Peripheral {
91+
const REGISTERS: *const () = pac::USBD::ptr() as *const ();
92+
}

errata.rs renamed to src/errata.rs

File renamed without changes.

src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! USB peripheral driver for nRF microcontrollers.
2+
3+
#![no_std]
4+
5+
mod errata;
6+
mod pac;
7+
mod usbd;
8+
9+
pub use usbd::Usbd;
10+
11+
/// A trait for device-specific USB peripherals. Implement this to add support for a new hardware
12+
/// platform. Peripherals that have this trait must have the same register block as NRF52 USBD
13+
/// peripherals.
14+
pub unsafe trait UsbPeripheral: Send + Sync {
15+
/// Pointer to the register block
16+
const REGISTERS: *const ();
17+
}

0 commit comments

Comments
 (0)