Skip to content

Commit 5099e8f

Browse files
bors[bot]jonas-schievinkjaparicwezDisasm
authored
Merge #295
295: USB support r=Dirbaio a=Disasm This PR is based on #144 and previous attempts. Co-authored-by: Jonas Schievink <[email protected]> Co-authored-by: Jorge Aparicio <[email protected]> Co-authored-by: Wez Furlong <[email protected]> Co-authored-by: Vadim Kaushan <[email protected]>
2 parents 22015fc + 9185196 commit 5099e8f

File tree

10 files changed

+221
-2
lines changed

10 files changed

+221
-2
lines changed

examples/usb/.gdbinit

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# disable "are you sure you want to quit?"
2+
define hook-quit
3+
set confirm off
4+
end
5+
6+
target remote :3333
7+
8+
# print demangled symbols by default
9+
set print asm-demangle on
10+
11+
monitor arm semihosting enable
12+
load
13+
cont

examples/usb/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "usb"
3+
version = "0.1.0"
4+
authors = ["Jonas Schievink <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
cortex-m-rt = "0.6.12"
9+
panic-semihosting = "0.5.3"
10+
nrf52840-pac = "0.9.0"
11+
usb-device = "0.2.7"
12+
usbd-serial = "0.1.0"
13+
14+
[dependencies.nrf52840-hal]
15+
version = "0.12.0"
16+
path = "../../nrf52840-hal"
17+

examples/usb/Embed.toml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
[default.probe]
2+
# USB vendor ID
3+
# usb_vid = "1337"
4+
# USB product ID
5+
# usb_pid = "1337"
6+
# Serial number
7+
# serial = "12345678"
8+
# The protocol to be used for communicating with the target.
9+
protocol = "Swd"
10+
# The speed in kHz of the data link to the target.
11+
# speed = 1337
12+
13+
[default.flashing]
14+
# Whether or not the target should be flashed.
15+
enabled = true
16+
# Whether or not the target should be halted after reset.
17+
# DEPRECATED, moved to reset section
18+
halt_afterwards = false
19+
# Whether or not bytes erased but not rewritten with data from the ELF
20+
# should be restored with their contents before erasing.
21+
restore_unwritten_bytes = false
22+
# The path where an SVG of the assembled flash layout should be written to.
23+
# flash_layout_output_path = "out.svg"
24+
25+
[default.reset]
26+
# Whether or not the target should be reset.
27+
# When flashing is enabled as well, the target will be reset after flashing.
28+
enabled = true
29+
# Whether or not the target should be halted after reset.
30+
halt_afterwards = false
31+
32+
[default.general]
33+
# The chip name of the chip to be debugged.
34+
chip = "nRF52840"
35+
# A list of chip descriptions to be loaded during runtime.
36+
chip_descriptions = []
37+
# The default log level to be used. Possible values are one of:
38+
# "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"
39+
log_level = "WARN"
40+
41+
[default.rtt]
42+
# Whether or not an RTTUI should be opened after flashing.
43+
# This is exclusive and cannot be used with GDB at the moment.
44+
enabled = true
45+
# A list of channel associations to be displayed. If left empty, all channels are displayed.
46+
channels = [
47+
# { up = 0, down = 0, name = "name", format = "String" }
48+
]
49+
# The duration in ms for which the logger should retry to attach to RTT.
50+
timeout = 3000
51+
# Whether timestamps in the RTTUI are enabled
52+
show_timestamps = true
53+
# Whether to save rtt history buffer on exit.
54+
log_enabled = false
55+
# Where to save rtt history buffer relative to manifest path.
56+
log_path = "./logs"
57+
58+
[default.gdb]
59+
# Whether or not a GDB server should be opened after flashing.
60+
# This is exclusive and cannot be used with RTT at the moment.
61+
enabled = false
62+
# The connection string in host:port format wher the GDB server will open a socket.
63+
# gdb_connection_string

examples/usb/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# USB examples
2+
3+
This demo provides two binaries:
4+
5+
- `serial`: a USB serial "echo" example.
6+
- `test_class`: exposes the test device from the `usb-device` crate.

examples/usb/src/bin/serial.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use panic_semihosting as _;
5+
6+
use cortex_m_rt::entry;
7+
use nrf52840_hal::clocks::Clocks;
8+
use nrf52840_hal::usbd::{UsbPeripheral, Usbd};
9+
use nrf52840_pac::Peripherals;
10+
use usb_device::device::{UsbDeviceBuilder, UsbVidPid};
11+
use usbd_serial::{SerialPort, USB_CLASS_CDC};
12+
13+
#[entry]
14+
fn main() -> ! {
15+
let periph = Peripherals::take().unwrap();
16+
let clocks = Clocks::new(periph.CLOCK);
17+
let clocks = clocks.enable_ext_hfosc();
18+
19+
let usb_bus = Usbd::new(UsbPeripheral::new(periph.USBD, &clocks));
20+
let mut serial = SerialPort::new(&usb_bus);
21+
22+
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
23+
.manufacturer("Fake company")
24+
.product("Serial port")
25+
.serial_number("TEST")
26+
.device_class(USB_CLASS_CDC)
27+
.max_packet_size_0(64) // (makes control transfers 8x faster)
28+
.build();
29+
30+
loop {
31+
if !usb_dev.poll(&mut [&mut serial]) {
32+
continue;
33+
}
34+
35+
let mut buf = [0u8; 64];
36+
37+
match serial.read(&mut buf) {
38+
Ok(count) if count > 0 => {
39+
// Echo back in upper case
40+
for c in buf[0..count].iter_mut() {
41+
if 0x61 <= *c && *c <= 0x7a {
42+
*c &= !0x20;
43+
}
44+
}
45+
46+
let mut write_offset = 0;
47+
while write_offset < count {
48+
match serial.write(&buf[write_offset..count]) {
49+
Ok(len) if len > 0 => {
50+
write_offset += len;
51+
}
52+
_ => {}
53+
}
54+
}
55+
}
56+
_ => {}
57+
}
58+
}
59+
}

examples/usb/src/bin/test_class.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use panic_semihosting as _;
5+
6+
use cortex_m_rt::entry;
7+
use nrf52840_hal::clocks::Clocks;
8+
use nrf52840_hal::usbd::{UsbPeripheral, Usbd};
9+
use nrf52840_pac::Peripherals;
10+
use usb_device::test_class::TestClass;
11+
12+
#[entry]
13+
fn main() -> ! {
14+
let periph = Peripherals::take().unwrap();
15+
let clocks = Clocks::new(periph.CLOCK);
16+
let clocks = clocks.enable_ext_hfosc();
17+
18+
let usb_bus = Usbd::new(UsbPeripheral::new(periph.USBD, &clocks));
19+
20+
let mut test = TestClass::new(&usb_bus);
21+
22+
let mut usb_dev = { test.make_device(&usb_bus) };
23+
24+
loop {
25+
if usb_dev.poll(&mut [&mut test]) {
26+
test.poll();
27+
}
28+
}
29+
}

nrf-hal-common/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ version = "0.9.0"
6363
optional = true
6464
version = "0.2.1"
6565

66+
[dependencies.nrf-usbd]
67+
version = "0.1.0"
68+
optional = true
69+
6670
[dependencies.embedded-hal]
6771
features = ["unproven"]
6872
version = "0.2.4"
@@ -73,6 +77,6 @@ doc = []
7377
52810 = ["nrf52810-pac"]
7478
52811 = ["nrf52811-pac"]
7579
52832 = ["nrf52832-pac"]
76-
52833 = ["nrf52833-pac"]
77-
52840 = ["nrf52840-pac"]
80+
52833 = ["nrf52833-pac", "nrf-usbd"]
81+
52840 = ["nrf52840-pac", "nrf-usbd"]
7882
9160 = ["nrf9160-pac"]

nrf-hal-common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ pub mod uart;
8080
pub mod uarte;
8181
#[cfg(not(feature = "9160"))]
8282
pub mod uicr;
83+
#[cfg(feature = "nrf-usbd")]
84+
pub mod usbd;
8385
pub mod wdt;
8486

8587
pub mod prelude {

nrf-hal-common/src/usbd.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use core::marker::PhantomData;
2+
3+
use crate::clocks::ExternalOscillator;
4+
use crate::pac::USBD;
5+
use crate::Clocks;
6+
7+
pub use nrf_usbd::Usbd;
8+
9+
pub struct UsbPeripheral<'a> {
10+
_usbd: USBD,
11+
_clocks: PhantomData<&'a ()>,
12+
}
13+
14+
impl<'a> UsbPeripheral<'a> {
15+
pub fn new<L, LSTAT>(usbd: USBD, _clocks: &'a Clocks<ExternalOscillator, L, LSTAT>) -> Self {
16+
Self {
17+
_usbd: usbd,
18+
_clocks: PhantomData,
19+
}
20+
}
21+
}
22+
23+
unsafe impl<'a> nrf_usbd::UsbPeripheral for UsbPeripheral<'a> {
24+
const REGISTERS: *const () = USBD::ptr() as *const _;
25+
}

xtask/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub static EXAMPLES: &[(&str, &[&str])] = &[
3838
("twim-demo", &[]),
3939
("twis-demo", &[]),
4040
("twis-dma-demo", &[]),
41+
("usb", &[]),
4142
("wdt-demo", &[]),
4243
];
4344

0 commit comments

Comments
 (0)