Skip to content

Commit

Permalink
Merge #295
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
5 people authored Jul 7, 2021
2 parents 22015fc + 9185196 commit 5099e8f
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 2 deletions.
13 changes: 13 additions & 0 deletions examples/usb/.gdbinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# disable "are you sure you want to quit?"
define hook-quit
set confirm off
end

target remote :3333

# print demangled symbols by default
set print asm-demangle on

monitor arm semihosting enable
load
cont
17 changes: 17 additions & 0 deletions examples/usb/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "usb"
version = "0.1.0"
authors = ["Jonas Schievink <[email protected]>"]
edition = "2018"

[dependencies]
cortex-m-rt = "0.6.12"
panic-semihosting = "0.5.3"
nrf52840-pac = "0.9.0"
usb-device = "0.2.7"
usbd-serial = "0.1.0"

[dependencies.nrf52840-hal]
version = "0.12.0"
path = "../../nrf52840-hal"

63 changes: 63 additions & 0 deletions examples/usb/Embed.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[default.probe]
# USB vendor ID
# usb_vid = "1337"
# USB product ID
# usb_pid = "1337"
# Serial number
# serial = "12345678"
# The protocol to be used for communicating with the target.
protocol = "Swd"
# The speed in kHz of the data link to the target.
# speed = 1337

[default.flashing]
# Whether or not the target should be flashed.
enabled = true
# Whether or not the target should be halted after reset.
# DEPRECATED, moved to reset section
halt_afterwards = false
# Whether or not bytes erased but not rewritten with data from the ELF
# should be restored with their contents before erasing.
restore_unwritten_bytes = false
# The path where an SVG of the assembled flash layout should be written to.
# flash_layout_output_path = "out.svg"

[default.reset]
# Whether or not the target should be reset.
# When flashing is enabled as well, the target will be reset after flashing.
enabled = true
# Whether or not the target should be halted after reset.
halt_afterwards = false

[default.general]
# The chip name of the chip to be debugged.
chip = "nRF52840"
# A list of chip descriptions to be loaded during runtime.
chip_descriptions = []
# The default log level to be used. Possible values are one of:
# "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"
log_level = "WARN"

[default.rtt]
# Whether or not an RTTUI should be opened after flashing.
# This is exclusive and cannot be used with GDB at the moment.
enabled = true
# A list of channel associations to be displayed. If left empty, all channels are displayed.
channels = [
# { up = 0, down = 0, name = "name", format = "String" }
]
# The duration in ms for which the logger should retry to attach to RTT.
timeout = 3000
# Whether timestamps in the RTTUI are enabled
show_timestamps = true
# Whether to save rtt history buffer on exit.
log_enabled = false
# Where to save rtt history buffer relative to manifest path.
log_path = "./logs"

[default.gdb]
# Whether or not a GDB server should be opened after flashing.
# This is exclusive and cannot be used with RTT at the moment.
enabled = false
# The connection string in host:port format wher the GDB server will open a socket.
# gdb_connection_string
6 changes: 6 additions & 0 deletions examples/usb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# USB examples

This demo provides two binaries:

- `serial`: a USB serial "echo" example.
- `test_class`: exposes the test device from the `usb-device` crate.
59 changes: 59 additions & 0 deletions examples/usb/src/bin/serial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#![no_std]
#![no_main]

use panic_semihosting as _;

use cortex_m_rt::entry;
use nrf52840_hal::clocks::Clocks;
use nrf52840_hal::usbd::{UsbPeripheral, Usbd};
use nrf52840_pac::Peripherals;
use usb_device::device::{UsbDeviceBuilder, UsbVidPid};
use usbd_serial::{SerialPort, USB_CLASS_CDC};

#[entry]
fn main() -> ! {
let periph = Peripherals::take().unwrap();
let clocks = Clocks::new(periph.CLOCK);
let clocks = clocks.enable_ext_hfosc();

let usb_bus = Usbd::new(UsbPeripheral::new(periph.USBD, &clocks));
let mut serial = SerialPort::new(&usb_bus);

let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.max_packet_size_0(64) // (makes control transfers 8x faster)
.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 => {
// 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;
}
_ => {}
}
}
}
_ => {}
}
}
}
29 changes: 29 additions & 0 deletions examples/usb/src/bin/test_class.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![no_std]
#![no_main]

use panic_semihosting as _;

use cortex_m_rt::entry;
use nrf52840_hal::clocks::Clocks;
use nrf52840_hal::usbd::{UsbPeripheral, Usbd};
use nrf52840_pac::Peripherals;
use usb_device::test_class::TestClass;

#[entry]
fn main() -> ! {
let periph = Peripherals::take().unwrap();
let clocks = Clocks::new(periph.CLOCK);
let clocks = clocks.enable_ext_hfosc();

let usb_bus = Usbd::new(UsbPeripheral::new(periph.USBD, &clocks));

let mut test = TestClass::new(&usb_bus);

let mut usb_dev = { test.make_device(&usb_bus) };

loop {
if usb_dev.poll(&mut [&mut test]) {
test.poll();
}
}
}
8 changes: 6 additions & 2 deletions nrf-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ version = "0.9.0"
optional = true
version = "0.2.1"

[dependencies.nrf-usbd]
version = "0.1.0"
optional = true

[dependencies.embedded-hal]
features = ["unproven"]
version = "0.2.4"
Expand All @@ -73,6 +77,6 @@ doc = []
52810 = ["nrf52810-pac"]
52811 = ["nrf52811-pac"]
52832 = ["nrf52832-pac"]
52833 = ["nrf52833-pac"]
52840 = ["nrf52840-pac"]
52833 = ["nrf52833-pac", "nrf-usbd"]
52840 = ["nrf52840-pac", "nrf-usbd"]
9160 = ["nrf9160-pac"]
2 changes: 2 additions & 0 deletions nrf-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ pub mod uart;
pub mod uarte;
#[cfg(not(feature = "9160"))]
pub mod uicr;
#[cfg(feature = "nrf-usbd")]
pub mod usbd;
pub mod wdt;

pub mod prelude {
Expand Down
25 changes: 25 additions & 0 deletions nrf-hal-common/src/usbd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use core::marker::PhantomData;

use crate::clocks::ExternalOscillator;
use crate::pac::USBD;
use crate::Clocks;

pub use nrf_usbd::Usbd;

pub struct UsbPeripheral<'a> {
_usbd: USBD,
_clocks: PhantomData<&'a ()>,
}

impl<'a> UsbPeripheral<'a> {
pub fn new<L, LSTAT>(usbd: USBD, _clocks: &'a Clocks<ExternalOscillator, L, LSTAT>) -> Self {
Self {
_usbd: usbd,
_clocks: PhantomData,
}
}
}

unsafe impl<'a> nrf_usbd::UsbPeripheral for UsbPeripheral<'a> {
const REGISTERS: *const () = USBD::ptr() as *const _;
}
1 change: 1 addition & 0 deletions xtask/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub static EXAMPLES: &[(&str, &[&str])] = &[
("twim-demo", &[]),
("twis-demo", &[]),
("twis-dma-demo", &[]),
("usb", &[]),
("wdt-demo", &[]),
];

Expand Down

0 comments on commit 5099e8f

Please sign in to comment.