mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2025-01-24 06:48:11 +00:00
- dk: API docs
- advanced: adapt to changes in usb2 dependency - dk: add reminder to connect the USB cable to port J3
This commit is contained in:
parent
e212e819b9
commit
31c331c1a3
8 changed files with 99 additions and 55 deletions
26
advanced/firmware/Cargo.lock
generated
26
advanced/firmware/Cargo.lock
generated
|
@ -60,7 +60,7 @@ version = "0.1.0"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
source = "git+https://github.com/rust-embedded/cortex-m#3136e01e708413774d7be2868705e1782c910027"
|
source = "git+https://github.com/rust-embedded/cortex-m#c9c7539233954822a6132f4bc13e5763371b5cb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"bitfield",
|
"bitfield",
|
||||||
|
@ -118,6 +118,7 @@ name = "dk"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
|
"cortex-m-rt",
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
"log",
|
"log",
|
||||||
"nrf52840-hal",
|
"nrf52840-hal",
|
||||||
|
@ -143,6 +144,7 @@ dependencies = [
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"cortex-m-rtfm",
|
"cortex-m-rtfm",
|
||||||
"dk",
|
"dk",
|
||||||
|
"heapless",
|
||||||
"log",
|
"log",
|
||||||
"panic-log",
|
"panic-log",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -201,9 +203,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.3.2"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
|
checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
@ -226,7 +228,7 @@ checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nrf-hal-common"
|
name = "nrf-hal-common"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "git+https://github.com/japaric/nrf-hal?branch=radio#443662d20591c3bef26a4fff2de03de90fec51aa"
|
source = "git+https://github.com/japaric/nrf-hal?branch=radio#d624e80e5724e4709081ed65abaf63271fe1eca7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast",
|
"cast",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
|
@ -241,7 +243,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nrf52840-hal"
|
name = "nrf52840-hal"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "git+https://github.com/japaric/nrf-hal?branch=radio#443662d20591c3bef26a4fff2de03de90fec51aa"
|
source = "git+https://github.com/japaric/nrf-hal?branch=radio#d624e80e5724e4709081ed65abaf63271fe1eca7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast",
|
"cast",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
|
@ -274,18 +276,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.17"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -362,9 +364,9 @@ checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.25"
|
version = "1.0.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f14a640819f79b72a710c0be059dce779f9339ae046c8bef12c361d56702146f"
|
checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -396,7 +398,7 @@ version = "0.1.0"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "usb2"
|
name = "usb2"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/japaric/usb2#c2b8118e667026f690c847782ebc5809aba749fe"
|
source = "git+https://github.com/japaric/usb2#6a8c4b1ed0db005dcf19694684524b33cc04abd2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
|
|
|
@ -16,6 +16,7 @@ cortex-m-rt = "0.6.12"
|
||||||
# TODO switch to RTIC before public release
|
# TODO switch to RTIC before public release
|
||||||
cortex-m-rtfm = "0.5.1"
|
cortex-m-rtfm = "0.5.1"
|
||||||
dk = { path = "../../boards/dk" }
|
dk = { path = "../../boards/dk" }
|
||||||
|
heapless = "0.5.5"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
panic-log = { path = "../../common/panic-log" }
|
panic-log = { path = "../../common/panic-log" }
|
||||||
usb = { path = "../common/usb" }
|
usb = { path = "../common/usb" }
|
||||||
|
|
|
@ -16,15 +16,10 @@ const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
usbd: USBD,
|
usbd: USBD,
|
||||||
ep0in: Ep0In,
|
ep0in: Ep0In,
|
||||||
#[init([0; 64])]
|
|
||||||
buffer: [u8; 64],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(resources = [buffer])]
|
#[init]
|
||||||
fn init(cx: init::Context) -> init::LateResources {
|
fn init(_cx: init::Context) -> init::LateResources {
|
||||||
let buffer: &'static mut [u8; 64] = cx.resources.buffer;
|
|
||||||
let ep0in = Ep0In::new(buffer);
|
|
||||||
|
|
||||||
let board = dk::init().unwrap();
|
let board = dk::init().unwrap();
|
||||||
|
|
||||||
usbd::init(board.power, &board.usbd);
|
usbd::init(board.power, &board.usbd);
|
||||||
|
@ -32,8 +27,8 @@ const APP: () = {
|
||||||
usbd::connect(&board.usbd);
|
usbd::connect(&board.usbd);
|
||||||
|
|
||||||
init::LateResources {
|
init::LateResources {
|
||||||
|
ep0in: board.ep0in,
|
||||||
usbd: board.usbd,
|
usbd: board.usbd,
|
||||||
ep0in,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,13 @@ use usb2::{GetDescriptor as Descriptor, StandardRequest as Request}; // crates.i
|
||||||
#[rtfm::app(device = dk)]
|
#[rtfm::app(device = dk)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init([0; 64])]
|
|
||||||
buffer: [u8; 64],
|
|
||||||
usbd: USBD,
|
usbd: USBD,
|
||||||
ep0in: Ep0In,
|
ep0in: Ep0In,
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(resources = [buffer])]
|
#[init]
|
||||||
fn init(cx: init::Context) -> init::LateResources {
|
fn init(_cx: init::Context) -> init::LateResources {
|
||||||
let buffer: &'static mut [u8; 64] = cx.resources.buffer;
|
|
||||||
let ep0in = Ep0In::new(buffer);
|
|
||||||
|
|
||||||
let board = dk::init().unwrap();
|
let board = dk::init().unwrap();
|
||||||
|
|
||||||
usbd::init(board.power, &board.usbd);
|
usbd::init(board.power, &board.usbd);
|
||||||
|
@ -36,7 +31,7 @@ const APP: () = {
|
||||||
init::LateResources {
|
init::LateResources {
|
||||||
usbd: board.usbd,
|
usbd: board.usbd,
|
||||||
state: State::Default,
|
state: State::Default,
|
||||||
ep0in,
|
ep0in: board.ep0in,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +67,7 @@ fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State) -> Result<(), ()> {
|
fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut State) -> Result<(), ()> {
|
||||||
let bmrequesttype = usbd.bmrequesttype.read().bits() as u8;
|
let bmrequesttype = usbd.bmrequesttype.read().bits() as u8;
|
||||||
let brequest = usbd.brequest.read().brequest().bits();
|
let brequest = usbd.brequest.read().brequest().bits();
|
||||||
let wlength = usbd::wlength(usbd);
|
let wlength = usbd::wlength(usbd);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
use dk::{
|
use dk::{
|
||||||
peripheral::USBD,
|
peripheral::USBD,
|
||||||
usbd::{self, Ep0In, Event},
|
usbd::{self, Ep0In, Event},
|
||||||
|
@ -18,10 +20,7 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_cx: init::Context) -> init::LateResources {
|
fn init(_cx: init::Context) -> init::LateResources {
|
||||||
static mut BUFFER: [u8; 64] = [0; 64];
|
|
||||||
|
|
||||||
let board = dk::init().unwrap();
|
let board = dk::init().unwrap();
|
||||||
let ep0in = Ep0In::new(BUFFER);
|
|
||||||
|
|
||||||
usbd::init(board.power, &board.usbd);
|
usbd::init(board.power, &board.usbd);
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ const APP: () = {
|
||||||
init::LateResources {
|
init::LateResources {
|
||||||
usbd: board.usbd,
|
usbd: board.usbd,
|
||||||
state: State::Default,
|
state: State::Default,
|
||||||
ep0in,
|
ep0in: board.ep0in,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +105,11 @@ fn ep0setup(usbd: &USBD, state: &mut State, ep0in: &mut Ep0In) -> Result<(), ()>
|
||||||
|
|
||||||
GetDescriptor::Configuration { index } => {
|
GetDescriptor::Configuration { index } => {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
let desc = usb2::configuration::Descriptor {
|
let mut full_desc = heapless::Vec::<u8, heapless::consts::U64>::new();
|
||||||
|
|
||||||
|
let conf_desc = usb2::configuration::Descriptor {
|
||||||
wTotalLength: usb2::configuration::Descriptor::SIZE.into(),
|
wTotalLength: usb2::configuration::Descriptor::SIZE.into(),
|
||||||
bNumInterfaces: 0,
|
bNumInterfaces: NonZeroU8::new(1).unwrap(),
|
||||||
bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(),
|
bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(),
|
||||||
iConfiguration: None,
|
iConfiguration: None,
|
||||||
bmAttributes: usb2::configuration::bmAttributes {
|
bmAttributes: usb2::configuration::bmAttributes {
|
||||||
|
@ -118,8 +119,22 @@ fn ep0setup(usbd: &USBD, state: &mut State, ep0in: &mut Ep0In) -> Result<(), ()>
|
||||||
bMaxPower: 250, // 500 mA
|
bMaxPower: 250, // 500 mA
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes = desc.bytes();
|
let iface_desc = usb2::interface::Descriptor {
|
||||||
ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd)?;
|
bInterfaceNumber: 0,
|
||||||
|
bAlternativeSetting: 0,
|
||||||
|
bNumEndpoints: 0,
|
||||||
|
bInterfaceClass: 0,
|
||||||
|
bInterfaceSubClass: 0,
|
||||||
|
bInterfaceProtocol: 0,
|
||||||
|
iInterface: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
full_desc.extend_from_slice(&conf_desc.bytes()).unwrap();
|
||||||
|
full_desc.extend_from_slice(&iface_desc.bytes()).unwrap();
|
||||||
|
ep0in.start(
|
||||||
|
&full_desc[..core::cmp::min(full_desc.len(), length.into())],
|
||||||
|
usbd,
|
||||||
|
)?;
|
||||||
} else {
|
} else {
|
||||||
// out of bounds access: stall the endpoint
|
// out of bounds access: stall the endpoint
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! Hardware Abstraction Layer (HAL) for the nRF52840 Development Kit
|
//! Hardware Abstraction Layer (HAL) for the nRF52840 Development Kit
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
|
@ -21,7 +23,10 @@ use hal::{
|
||||||
use log::{LevelFilter, Log};
|
use log::{LevelFilter, Log};
|
||||||
use rtt_target::{rprintln, rtt_init_print};
|
use rtt_target::{rprintln, rtt_init_print};
|
||||||
|
|
||||||
use crate::peripheral::{POWER, USBD};
|
use crate::{
|
||||||
|
peripheral::{POWER, USBD},
|
||||||
|
usbd::Ep0In,
|
||||||
|
};
|
||||||
|
|
||||||
mod errata;
|
mod errata;
|
||||||
pub mod peripheral;
|
pub mod peripheral;
|
||||||
|
@ -29,13 +34,20 @@ pub mod usbd;
|
||||||
|
|
||||||
/// Components on the board
|
/// Components on the board
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
|
/// LEDs
|
||||||
pub leds: Leds,
|
pub leds: Leds,
|
||||||
|
/// Radio interface
|
||||||
// TODO put behind feature flag (off in advanced workshop)
|
// TODO put behind feature flag (off in advanced workshop)
|
||||||
pub radio: Radio<'static>,
|
pub radio: Radio<'static>,
|
||||||
|
/// Timer
|
||||||
pub timer: Timer,
|
pub timer: Timer,
|
||||||
|
/// USBD (Universal Serial Bus Device) peripheral
|
||||||
// TODO put behind feature flag (off in beginner workshop)
|
// TODO put behind feature flag (off in beginner workshop)
|
||||||
pub usbd: USBD,
|
pub usbd: USBD,
|
||||||
|
/// POWER (Power Supply) peripheral
|
||||||
pub power: POWER,
|
pub power: POWER,
|
||||||
|
/// USB control endpoint 0
|
||||||
|
pub ep0in: Ep0In,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All LEDs on the board
|
/// All LEDs on the board
|
||||||
|
@ -149,7 +161,8 @@ pub fn init() -> Result<Board, ()> {
|
||||||
cortex_m::Peripherals::take(),
|
cortex_m::Peripherals::take(),
|
||||||
hal::target::Peripherals::take(),
|
hal::target::Peripherals::take(),
|
||||||
) {
|
) {
|
||||||
// NOTE(unsafe) this branch runs at most once
|
// NOTE(static mut) this branch runs at most once
|
||||||
|
static mut EP0IN_BUF: [u8; 64] = [0; 64];
|
||||||
static mut CLOCKS: Option<Clocks<ExternalOscillator, ExternalOscillator, LfOscStarted>> =
|
static mut CLOCKS: Option<Clocks<ExternalOscillator, ExternalOscillator, LfOscStarted>> =
|
||||||
None;
|
None;
|
||||||
|
|
||||||
|
@ -210,6 +223,7 @@ pub fn init() -> Result<Board, ()> {
|
||||||
timer: Timer { inner: timer },
|
timer: Timer { inner: timer },
|
||||||
usbd: periph.USBD,
|
usbd: periph.USBD,
|
||||||
power: periph.POWER,
|
power: periph.POWER,
|
||||||
|
ep0in: unsafe { Ep0In::new(&mut EP0IN_BUF) },
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
|
//! Low level access to the nRF52840 peripheral
|
||||||
|
|
||||||
pub use hal::target::{POWER, USBD};
|
pub use hal::target::{POWER, USBD};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use core::sync::atomic::{self, Ordering};
|
//! USBD peripheral
|
||||||
|
|
||||||
use cortex_m::asm;
|
use core::sync::atomic::{self, Ordering};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errata,
|
errata,
|
||||||
|
@ -14,17 +14,23 @@ pub struct Ep0In {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ep0In {
|
impl Ep0In {
|
||||||
pub fn new(buffer: &'static mut [u8; 64]) -> Self {
|
/// # Safety
|
||||||
|
/// Must be created at most once (singleton)
|
||||||
|
pub(crate) unsafe fn new(buffer: &'static mut [u8; 64]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
buffer,
|
||||||
busy: false,
|
busy: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starts a data transfer over endpoint 0
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function panics if the last transfer was not finished by calling the `end` function
|
||||||
pub fn start(&mut self, bytes: &[u8], usbd: &USBD) -> Result<(), ()> {
|
pub fn start(&mut self, bytes: &[u8], usbd: &USBD) -> Result<(), ()> {
|
||||||
if self.busy {
|
if self.busy {
|
||||||
log::error!("EP0IN: last transfer not completed");
|
panic!("EP0IN: last transfer has not completed");
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.len() > self.buffer.len() {
|
if bytes.len() > self.buffer.len() {
|
||||||
|
@ -56,12 +62,17 @@ impl Ep0In {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Completes a data transfer
|
||||||
|
///
|
||||||
|
/// This function must be called after the EP0DATADONE event is raised
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function panics if called before `start` or before the EP0DATADONE event is raised by
|
||||||
|
/// the hardware
|
||||||
pub fn end(&mut self, usbd: &USBD) {
|
pub fn end(&mut self, usbd: &USBD) {
|
||||||
if usbd.events_ep0datadone.read().bits() == 0 {
|
if usbd.events_ep0datadone.read().bits() == 0 {
|
||||||
log::error!("Ep0In.end called before the EP0DATADONE event was raised");
|
panic!("Ep0In.end called before the EP0DATADONE event was raised");
|
||||||
loop {
|
|
||||||
asm::bkpt();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// DMA transfer complete
|
// DMA transfer complete
|
||||||
dma_end();
|
dma_end();
|
||||||
|
@ -77,7 +88,7 @@ impl Ep0In {
|
||||||
//
|
//
|
||||||
// This function call *must* be *followed* by a memory *store* operation. Memory operations that
|
// This function call *must* be *followed* by a memory *store* operation. Memory operations that
|
||||||
// follow this function call will *not* be moved, by the compiler or the instruction pipeline, to
|
// follow this function call will *not* be moved, by the compiler or the instruction pipeline, to
|
||||||
// *after* the function call.
|
// *after* the function call.
|
||||||
fn dma_start() {
|
fn dma_start() {
|
||||||
atomic::fence(Ordering::Release);
|
atomic::fence(Ordering::Release);
|
||||||
}
|
}
|
||||||
|
@ -87,21 +98,28 @@ fn dma_start() {
|
||||||
//
|
//
|
||||||
// This function call *must* be *preceded* by a memory *load* operation. Memory operations that
|
// This function call *must* be *preceded* by a memory *load* operation. Memory operations that
|
||||||
// follow this function call will *not* be moved, by the compiler or the instruction pipeline, to
|
// follow this function call will *not* be moved, by the compiler or the instruction pipeline, to
|
||||||
// *before* the function call.
|
// *before* the function call.
|
||||||
fn dma_end() {
|
fn dma_end() {
|
||||||
atomic::fence(Ordering::Acquire);
|
atomic::fence(Ordering::Acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initializes the USBD peripheral
|
||||||
// NOTE will be called from user code; at that point the high frequency clock source has already
|
// NOTE will be called from user code; at that point the high frequency clock source has already
|
||||||
// been configured to use to the external crystal
|
// been configured to use to the external crystal
|
||||||
// Reference: section 6.35.4 of the nRF52840 Product Specification
|
// Reference: section 6.35.4 of the nRF52840 Product Specification
|
||||||
pub fn init(power: POWER, usbd: &USBD) {
|
pub fn init(power: POWER, usbd: &USBD) {
|
||||||
|
let mut once = true;
|
||||||
|
|
||||||
// wait until the USB has been connected
|
// wait until the USB has been connected
|
||||||
while power.events_usbdetected.read().bits() == 0 {
|
while power.events_usbdetected.read().bits() == 0 {
|
||||||
power.events_usbdetected.reset();
|
if once {
|
||||||
|
log::info!("waiting for USB connection on port J3");
|
||||||
|
once = false;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
power.events_usbdetected.reset();
|
||||||
|
|
||||||
// workaround silicon bug
|
// workaround silicon bug
|
||||||
unsafe { errata::e187a() }
|
unsafe { errata::e187a() }
|
||||||
|
@ -147,6 +165,7 @@ pub fn disconnect(usbd: &USBD) {
|
||||||
usbd.usbpullup.reset();
|
usbd.usbpullup.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stalls endpoint 0
|
||||||
pub fn ep0stall(usbd: &USBD) {
|
pub fn ep0stall(usbd: &USBD) {
|
||||||
usbd.tasks_ep0stall.write(|w| w.tasks_ep0stall().set_bit());
|
usbd.tasks_ep0stall.write(|w| w.tasks_ep0stall().set_bit());
|
||||||
}
|
}
|
||||||
|
@ -176,7 +195,7 @@ pub fn next_event(usbd: &USBD) -> Option<Event> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if usbd.events_ep0datadone.read().bits() != 0 {
|
if usbd.events_ep0datadone.read().bits() != 0 {
|
||||||
// this will be cleared elsewhere
|
// this will be cleared by the `Ep0In.end` method
|
||||||
// usbd.events_ep0datadone.reset();
|
// usbd.events_ep0datadone.reset();
|
||||||
|
|
||||||
return Some(Event::UsbEp0DataDone);
|
return Some(Event::UsbEp0DataDone);
|
||||||
|
@ -195,21 +214,22 @@ pub fn next_event(usbd: &USBD) -> Option<Event> {
|
||||||
pub fn todo(usbd: &USBD) {
|
pub fn todo(usbd: &USBD) {
|
||||||
disconnect(usbd);
|
disconnect(usbd);
|
||||||
log::error!("unimplemented");
|
log::error!("unimplemented");
|
||||||
loop {
|
crate::exit()
|
||||||
asm::bkpt()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads the WLENGTHL and WLENGTHH registers and returns the 16-bit WLENGTH component of a setup packet
|
||||||
pub fn wlength(usbd: &USBD) -> u16 {
|
pub fn wlength(usbd: &USBD) -> u16 {
|
||||||
u16::from(usbd.wlengthl.read().wlengthl().bits())
|
u16::from(usbd.wlengthl.read().wlengthl().bits())
|
||||||
| u16::from(usbd.wlengthh.read().wlengthh().bits()) << 8
|
| u16::from(usbd.wlengthh.read().wlengthh().bits()) << 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads the WINDEXL and WINDEXH registers and returns the 16-bit WINDEX component of a setup packet
|
||||||
pub fn windex(usbd: &USBD) -> u16 {
|
pub fn windex(usbd: &USBD) -> u16 {
|
||||||
u16::from(usbd.windexl.read().windexl().bits())
|
u16::from(usbd.windexl.read().windexl().bits())
|
||||||
| u16::from(usbd.windexh.read().windexh().bits()) << 8
|
| u16::from(usbd.windexh.read().windexh().bits()) << 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads the WVALUEL and WVALUEH registers and returns the 16-bit WVALUE component of a setup packet
|
||||||
pub fn wvalue(usbd: &USBD) -> u16 {
|
pub fn wvalue(usbd: &USBD) -> u16 {
|
||||||
u16::from(usbd.wvaluel.read().wvaluel().bits())
|
u16::from(usbd.wvaluel.read().wvaluel().bits())
|
||||||
| u16::from(usbd.wvalueh.read().wvalueh().bits()) << 8
|
| u16::from(usbd.wvalueh.read().wvalueh().bits()) << 8
|
||||||
|
|
Loading…
Reference in a new issue