Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB support #295

Merged
merged 39 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
0fbc358
wip
jonas-schievink Feb 20, 2020
86e84a8
errata: use volatile operations
japaric May 4, 2020
261eeae
4 byte align bulk/interrupt endpoint buffers
japaric May 4, 2020
faf0cb3
don't return PollResult::Data when there's no data
japaric May 7, 2020
2c3693b
EP0: shoehorn status stage
japaric May 7, 2020
b9e0eb4
make bulk reads works
japaric May 7, 2020
714b4f8
demand a Clocks token
japaric May 7, 2020
788ff0f
remove stray print statement
japaric May 7, 2020
b84300b
make the example compile again
japaric May 7, 2020
d1d70b4
remove patch
japaric May 11, 2020
7fb2998
rebase fixes
japaric May 11, 2020
5b216e2
Rebase #144, formerly #133 to pull in USB for nrf52480
wez Feb 14, 2021
1c87602
fixup CI for newly add usb test
wez Feb 14, 2021
f36a7e0
Reset shorts on SETUP to prevent spurious status stages
Disasm Feb 17, 2021
fa4011e
Introduce EP0State
Disasm Feb 17, 2021
c6d6aeb
Rewrite read/write logic
Disasm Feb 17, 2021
b938651
Add hack to detect interrupted IN transfers
Disasm Feb 17, 2021
1b3e38b
Inhibit SetAddress response
Disasm Feb 17, 2021
e78f3d0
Apply suggestions from code review
Disasm Feb 17, 2021
a7a7e84
Replace unsafe borrow with get() and set()
Disasm Feb 18, 2021
84ccc05
Issue a status stage when the transfer data is fully written
Disasm Feb 21, 2021
5d0c0eb
Don't prepare DMA transfer in read_control_setup
Disasm Feb 21, 2021
048e51d
Don't prepare DMA transfers in reset
Disasm Feb 21, 2021
7ad844a
Remove backing buffers
Disasm Feb 21, 2021
48b50e6
Track IN endpoint state
Disasm Feb 26, 2021
6ffd9e1
Remove redundant clear operation
Disasm Jun 4, 2021
922ced5
Check EPDATASTATUS inside write()
Disasm Jun 4, 2021
07b01ec
Merge remote-tracking branch 'upstream/master' into usb
Disasm Jun 4, 2021
4f33ab8
Cleanup
Disasm Jun 5, 2021
2e469df
Implement is_stalled()
Disasm Jun 5, 2021
f55b541
Add serial and test_class examples
Disasm Jun 5, 2021
d93fc5e
Fix warning
Disasm Jun 5, 2021
74b797e
Cleanup examples
Disasm Jun 12, 2021
9ce50b5
Fix USB demo
Jul 6, 2021
6ede424
Clean up Cargo features, support nRF52833
Jul 6, 2021
dbe0b5a
Add a 1ms delay to `force_reset`
Jul 6, 2021
844b782
Use nrf-usbd
jonas-schievink Jul 6, 2021
3ea49b7
Use crates.io version of nrf-usbd
jonas-schievink Jul 7, 2021
9185196
Address review comments
jonas-schievink Jul 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/usb/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = 'arm-none-eabi-gdb'
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"

14 changes: 14 additions & 0 deletions examples/usb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# spi-demo
SPIM demonstation code.
Connect a resistor between pin 22 and 23 on the demo board to feed MOSI directly back to MISO
If all tests pass all four Led (Led1 to Led4) will light up, in case of error only at least one of the Led will remain turned off.


## HW connections
Pin Connecton
P0.24 SPIclk
P0.23 MOSI
P0.22 MISO

This is designed for nRF52-DK board:
https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK
jonas-schievink marked this conversation as resolved.
Show resolved Hide resolved
59 changes: 59 additions & 0 deletions examples/usb/examples/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::usbd::Usbd;
use nrf52840_hal::clocks::Clocks;
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(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/examples/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::usbd::Usbd;
use nrf52840_hal::clocks::Clocks;
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(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();
}
}
}
42 changes: 42 additions & 0 deletions examples/usb/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#![no_std]
#![no_main]

use panic_semihosting as _;

use cortex_m_rt::entry;
use nrf52840_hal::prelude::*;
use nrf52840_hal::timer::{OneShot, Timer};
use nrf52840_hal::usbd::Usbd;
use nrf52840_hal::clocks::Clocks;
use nrf52840_pac::{Peripherals, TIMER0};
use usb_device::device::{UsbDeviceBuilder, UsbDeviceState, 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 mut timer = Timer::periodic(periph.TIMER0);
timer.start(Timer::<TIMER0, OneShot>::TICKS_PER_SECOND);

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

let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.product("nRF52840 Serial Port Demo")
.device_class(USB_CLASS_CDC)
.max_packet_size_0(64) // (makes control transfers 8x faster)
.build();

loop {
usb_dev.poll(&mut [&mut serial]);

if usb_dev.state() == UsbDeviceState::Configured && serial.dtr() {
if timer.wait().is_ok() {
serial.write(b"Hello, world!\n").ok();
}
}
}
}
jonas-schievink marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 5 additions & 1 deletion nrf-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ version = "0.2.3"
optional = true
version = "0.9.0"

[dependencies.usb-device]
version = "0.2.7"
optional = true

[dependencies.nrf52810-pac]
optional = true
version = "0.9.0"
Expand Down Expand Up @@ -74,5 +78,5 @@ doc = []
52811 = ["nrf52811-pac"]
52832 = ["nrf52832-pac"]
52833 = ["nrf52833-pac"]
52840 = ["nrf52840-pac"]
52840 = ["nrf52840-pac", "usb-device"]
jonas-schievink marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -81,6 +81,8 @@ pub mod uarte;
#[cfg(not(feature = "9160"))]
pub mod uicr;
pub mod wdt;
#[cfg(feature = "52840")]
jonas-schievink marked this conversation as resolved.
Show resolved Hide resolved
pub mod usbd;

pub mod prelude {
pub use crate::hal::digital::v2::*;
Expand Down
57 changes: 57 additions & 0 deletions nrf-hal-common/src/usbd/errata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/// Writes `val` to `addr`. Used to apply Errata workarounds.
unsafe fn poke(addr: u32, val: u32) {
(addr as *mut u32).write_volatile(val);
}

/// Reads 32 bits from `addr`.
unsafe fn peek(addr: u32) -> u32 {
(addr as *mut u32).read_volatile()
}

pub fn pre_enable() {
// Works around Erratum 187 on chip revisions 1 and 2.
unsafe {
poke(0x4006EC00, 0x00009375);
poke(0x4006ED14, 0x00000003);
poke(0x4006EC00, 0x00009375);
}

pre_wakeup();
}

pub fn post_enable() {
post_wakeup();

// Works around Erratum 187 on chip revisions 1 and 2.
unsafe {
poke(0x4006EC00, 0x00009375);
poke(0x4006ED14, 0x00000000);
poke(0x4006EC00, 0x00009375);
}
}

pub fn pre_wakeup() {
// Works around Erratum 171 on chip revisions 1 and 2.

unsafe {
if peek(0x4006EC00) == 0x00000000 {
poke(0x4006EC00, 0x00009375);
}

poke(0x4006EC14, 0x000000C0);
poke(0x4006EC00, 0x00009375);
}
}

pub fn post_wakeup() {
// Works around Erratum 171 on chip revisions 1 and 2.

unsafe {
if peek(0x4006EC00) == 0x00000000 {
poke(0x4006EC00, 0x00009375);
}

poke(0x4006EC14, 0x00000000);
poke(0x4006EC00, 0x00009375);
}
}
Loading