nrf/usb: switch to new interrupt binding, fix vbus detect on nrf53.
This commit is contained in:
parent
5913553cb1
commit
5249996d28
@ -2,10 +2,12 @@
|
||||
|
||||
#![macro_use]
|
||||
|
||||
pub mod vbus_detect;
|
||||
|
||||
use core::future::poll_fn;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering};
|
||||
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use cortex_m::peripheral::NVIC;
|
||||
@ -15,7 +17,8 @@ use embassy_usb_driver as driver;
|
||||
use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
|
||||
use pac::usbd::RegisterBlock;
|
||||
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use self::vbus_detect::VbusDetect;
|
||||
use crate::interrupt::{self, Interrupt, InterruptExt};
|
||||
use crate::util::slice_in_ram;
|
||||
use crate::{pac, Peripheral};
|
||||
|
||||
@ -26,185 +29,13 @@ static EP_IN_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
|
||||
static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
|
||||
static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
/// Trait for detecting USB VBUS power.
|
||||
///
|
||||
/// There are multiple ways to detect USB power. The behavior
|
||||
/// here provides a hook into determining whether it is.
|
||||
pub trait VbusDetect {
|
||||
/// Report whether power is detected.
|
||||
///
|
||||
/// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
|
||||
/// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
|
||||
fn is_usb_detected(&self) -> bool;
|
||||
|
||||
/// Wait until USB power is ready.
|
||||
///
|
||||
/// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
|
||||
/// `USBPWRRDY` event from the `POWER` peripheral.
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()>;
|
||||
/// Interrupt handler.
|
||||
pub struct InterruptHandler<T: Instance> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
|
||||
///
|
||||
/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
|
||||
/// to POWER. In that case, use [`VbusDetectSignal`].
|
||||
#[cfg(not(feature = "_nrf5340-app"))]
|
||||
pub struct HardwareVbusDetect {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
static POWER_WAKER: AtomicWaker = NEW_AW;
|
||||
|
||||
#[cfg(not(feature = "_nrf5340-app"))]
|
||||
impl HardwareVbusDetect {
|
||||
/// Create a new `VbusDetectNative`.
|
||||
pub fn new(power_irq: impl Interrupt) -> Self {
|
||||
let regs = unsafe { &*pac::POWER::ptr() };
|
||||
|
||||
power_irq.set_handler(Self::on_interrupt);
|
||||
power_irq.unpend();
|
||||
power_irq.enable();
|
||||
|
||||
regs.intenset
|
||||
.write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
|
||||
|
||||
Self { _private: () }
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "_nrf5340-app"))]
|
||||
fn on_interrupt(_: *mut ()) {
|
||||
let regs = unsafe { &*pac::POWER::ptr() };
|
||||
|
||||
if regs.events_usbdetected.read().bits() != 0 {
|
||||
regs.events_usbdetected.reset();
|
||||
BUS_WAKER.wake();
|
||||
}
|
||||
|
||||
if regs.events_usbremoved.read().bits() != 0 {
|
||||
regs.events_usbremoved.reset();
|
||||
BUS_WAKER.wake();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
|
||||
if regs.events_usbpwrrdy.read().bits() != 0 {
|
||||
regs.events_usbpwrrdy.reset();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "_nrf5340-app"))]
|
||||
impl VbusDetect for HardwareVbusDetect {
|
||||
fn is_usb_detected(&self) -> bool {
|
||||
let regs = unsafe { &*pac::POWER::ptr() };
|
||||
regs.usbregstatus.read().vbusdetect().is_vbus_present()
|
||||
}
|
||||
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
let regs = unsafe { &*pac::POWER::ptr() };
|
||||
|
||||
if regs.usbregstatus.read().outputrdy().is_ready() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if !self.is_usb_detected() {
|
||||
Poll::Ready(Err(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// Software-backed [`VbusDetect`] implementation.
|
||||
///
|
||||
/// This implementation does not interact with the hardware, it allows user code
|
||||
/// to notify the power events by calling functions instead.
|
||||
///
|
||||
/// This is suitable for use with the nRF softdevice, by calling the functions
|
||||
/// when the softdevice reports power-related events.
|
||||
pub struct SoftwareVbusDetect {
|
||||
usb_detected: AtomicBool,
|
||||
power_ready: AtomicBool,
|
||||
}
|
||||
|
||||
impl SoftwareVbusDetect {
|
||||
/// Create a new `SoftwareVbusDetect`.
|
||||
pub fn new(usb_detected: bool, power_ready: bool) -> Self {
|
||||
BUS_WAKER.wake();
|
||||
|
||||
Self {
|
||||
usb_detected: AtomicBool::new(usb_detected),
|
||||
power_ready: AtomicBool::new(power_ready),
|
||||
}
|
||||
}
|
||||
|
||||
/// Report whether power was detected.
|
||||
///
|
||||
/// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
|
||||
pub fn detected(&self, detected: bool) {
|
||||
self.usb_detected.store(detected, Ordering::Relaxed);
|
||||
self.power_ready.store(false, Ordering::Relaxed);
|
||||
BUS_WAKER.wake();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
|
||||
/// Report when USB power is ready.
|
||||
///
|
||||
/// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
|
||||
pub fn ready(&self) {
|
||||
self.power_ready.store(true, Ordering::Relaxed);
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
}
|
||||
|
||||
impl VbusDetect for &SoftwareVbusDetect {
|
||||
fn is_usb_detected(&self) -> bool {
|
||||
self.usb_detected.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
|
||||
if self.power_ready.load(Ordering::Relaxed) {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if !self.usb_detected.load(Ordering::Relaxed) {
|
||||
Poll::Ready(Err(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// USB driver.
|
||||
pub struct Driver<'d, T: Instance, P: VbusDetect> {
|
||||
_p: PeripheralRef<'d, T>,
|
||||
alloc_in: Allocator,
|
||||
alloc_out: Allocator,
|
||||
usb_supply: P,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
|
||||
/// Create a new USB driver.
|
||||
pub fn new(usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd, usb_supply: P) -> Self {
|
||||
into_ref!(usb, irq);
|
||||
irq.set_handler(Self::on_interrupt);
|
||||
irq.unpend();
|
||||
irq.enable();
|
||||
|
||||
Self {
|
||||
_p: usb,
|
||||
alloc_in: Allocator::new(),
|
||||
alloc_out: Allocator::new(),
|
||||
usb_supply,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_interrupt(_: *mut ()) {
|
||||
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {
|
||||
let regs = T::regs();
|
||||
|
||||
if regs.events_usbreset.read().bits() != 0 {
|
||||
@ -255,11 +86,40 @@ impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P> {
|
||||
/// USB driver.
|
||||
pub struct Driver<'d, T: Instance, V: VbusDetect> {
|
||||
_p: PeripheralRef<'d, T>,
|
||||
alloc_in: Allocator,
|
||||
alloc_out: Allocator,
|
||||
vbus_detect: V,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> {
|
||||
/// Create a new USB driver.
|
||||
pub fn new(
|
||||
usb: impl Peripheral<P = T> + 'd,
|
||||
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
vbus_detect: V,
|
||||
) -> Self {
|
||||
into_ref!(usb);
|
||||
|
||||
unsafe { T::Interrupt::steal() }.unpend();
|
||||
unsafe { T::Interrupt::steal() }.enable();
|
||||
|
||||
Self {
|
||||
_p: usb,
|
||||
alloc_in: Allocator::new(),
|
||||
alloc_out: Allocator::new(),
|
||||
vbus_detect,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V> {
|
||||
type EndpointOut = Endpoint<'d, T, Out>;
|
||||
type EndpointIn = Endpoint<'d, T, In>;
|
||||
type ControlPipe = ControlPipe<'d, T>;
|
||||
type Bus = Bus<'d, T, P>;
|
||||
type Bus = Bus<'d, T, V>;
|
||||
|
||||
fn alloc_endpoint_in(
|
||||
&mut self,
|
||||
@ -298,7 +158,7 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
|
||||
Bus {
|
||||
_p: unsafe { self._p.clone_unchecked() },
|
||||
power_available: false,
|
||||
usb_supply: self.usb_supply,
|
||||
vbus_detect: self.vbus_detect,
|
||||
},
|
||||
ControlPipe {
|
||||
_p: self._p,
|
||||
@ -309,13 +169,13 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
|
||||
}
|
||||
|
||||
/// USB bus.
|
||||
pub struct Bus<'d, T: Instance, P: VbusDetect> {
|
||||
pub struct Bus<'d, T: Instance, V: VbusDetect> {
|
||||
_p: PeripheralRef<'d, T>,
|
||||
power_available: bool,
|
||||
usb_supply: P,
|
||||
vbus_detect: V,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
|
||||
impl<'d, T: Instance, V: VbusDetect> driver::Bus for Bus<'d, T, V> {
|
||||
async fn enable(&mut self) {
|
||||
let regs = T::regs();
|
||||
|
||||
@ -347,7 +207,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
|
||||
w
|
||||
});
|
||||
|
||||
if self.usb_supply.wait_power_ready().await.is_ok() {
|
||||
if self.vbus_detect.wait_power_ready().await.is_ok() {
|
||||
// Enable the USB pullup, allowing enumeration.
|
||||
regs.usbpullup.write(|w| w.connect().enabled());
|
||||
trace!("enabled");
|
||||
@ -406,7 +266,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
|
||||
trace!("USB event: ready");
|
||||
}
|
||||
|
||||
if self.usb_supply.is_usb_detected() != self.power_available {
|
||||
if self.vbus_detect.is_usb_detected() != self.power_available {
|
||||
self.power_available = !self.power_available;
|
||||
if self.power_available {
|
||||
trace!("Power event: available");
|
177
embassy-nrf/src/usb/vbus_detect.rs
Normal file
177
embassy-nrf/src/usb/vbus_detect.rs
Normal file
@ -0,0 +1,177 @@
|
||||
//! Trait and implementations for performing VBUS detection.
|
||||
|
||||
use core::future::poll_fn;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::BUS_WAKER;
|
||||
use crate::interrupt::{self, Interrupt, InterruptExt};
|
||||
use crate::pac;
|
||||
|
||||
/// Trait for detecting USB VBUS power.
|
||||
///
|
||||
/// There are multiple ways to detect USB power. The behavior
|
||||
/// here provides a hook into determining whether it is.
|
||||
pub trait VbusDetect {
|
||||
/// Report whether power is detected.
|
||||
///
|
||||
/// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
|
||||
/// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
|
||||
fn is_usb_detected(&self) -> bool;
|
||||
|
||||
/// Wait until USB power is ready.
|
||||
///
|
||||
/// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
|
||||
/// `USBPWRRDY` event from the `POWER` peripheral.
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "_nrf5340"))]
|
||||
type UsbRegIrq = interrupt::POWER_CLOCK;
|
||||
#[cfg(feature = "_nrf5340")]
|
||||
type UsbRegIrq = interrupt::USBREGULATOR;
|
||||
|
||||
#[cfg(not(feature = "_nrf5340"))]
|
||||
type UsbRegPeri = pac::POWER;
|
||||
#[cfg(feature = "_nrf5340")]
|
||||
type UsbRegPeri = pac::USBREGULATOR;
|
||||
|
||||
/// Interrupt handler.
|
||||
pub struct InterruptHandler {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl interrupt::Handler<UsbRegIrq> for InterruptHandler {
|
||||
unsafe fn on_interrupt() {
|
||||
let regs = unsafe { &*UsbRegPeri::ptr() };
|
||||
|
||||
if regs.events_usbdetected.read().bits() != 0 {
|
||||
regs.events_usbdetected.reset();
|
||||
BUS_WAKER.wake();
|
||||
}
|
||||
|
||||
if regs.events_usbremoved.read().bits() != 0 {
|
||||
regs.events_usbremoved.reset();
|
||||
BUS_WAKER.wake();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
|
||||
if regs.events_usbpwrrdy.read().bits() != 0 {
|
||||
regs.events_usbpwrrdy.reset();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
|
||||
///
|
||||
/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
|
||||
/// to POWER. In that case, use [`VbusDetectSignal`].
|
||||
pub struct HardwareVbusDetect {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
static POWER_WAKER: AtomicWaker = AtomicWaker::new();
|
||||
|
||||
impl HardwareVbusDetect {
|
||||
/// Create a new `VbusDetectNative`.
|
||||
pub fn new(_irq: impl interrupt::Binding<UsbRegIrq, InterruptHandler> + 'static) -> Self {
|
||||
let regs = unsafe { &*UsbRegPeri::ptr() };
|
||||
|
||||
unsafe { UsbRegIrq::steal() }.unpend();
|
||||
unsafe { UsbRegIrq::steal() }.enable();
|
||||
|
||||
regs.intenset
|
||||
.write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
|
||||
|
||||
Self { _private: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl VbusDetect for HardwareVbusDetect {
|
||||
fn is_usb_detected(&self) -> bool {
|
||||
let regs = unsafe { &*UsbRegPeri::ptr() };
|
||||
regs.usbregstatus.read().vbusdetect().is_vbus_present()
|
||||
}
|
||||
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
let regs = unsafe { &*UsbRegPeri::ptr() };
|
||||
|
||||
if regs.usbregstatus.read().outputrdy().is_ready() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if !self.is_usb_detected() {
|
||||
Poll::Ready(Err(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// Software-backed [`VbusDetect`] implementation.
|
||||
///
|
||||
/// This implementation does not interact with the hardware, it allows user code
|
||||
/// to notify the power events by calling functions instead.
|
||||
///
|
||||
/// This is suitable for use with the nRF softdevice, by calling the functions
|
||||
/// when the softdevice reports power-related events.
|
||||
pub struct SoftwareVbusDetect {
|
||||
usb_detected: AtomicBool,
|
||||
power_ready: AtomicBool,
|
||||
}
|
||||
|
||||
impl SoftwareVbusDetect {
|
||||
/// Create a new `SoftwareVbusDetect`.
|
||||
pub fn new(usb_detected: bool, power_ready: bool) -> Self {
|
||||
BUS_WAKER.wake();
|
||||
|
||||
Self {
|
||||
usb_detected: AtomicBool::new(usb_detected),
|
||||
power_ready: AtomicBool::new(power_ready),
|
||||
}
|
||||
}
|
||||
|
||||
/// Report whether power was detected.
|
||||
///
|
||||
/// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
|
||||
pub fn detected(&self, detected: bool) {
|
||||
self.usb_detected.store(detected, Ordering::Relaxed);
|
||||
self.power_ready.store(false, Ordering::Relaxed);
|
||||
BUS_WAKER.wake();
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
|
||||
/// Report when USB power is ready.
|
||||
///
|
||||
/// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
|
||||
pub fn ready(&self) {
|
||||
self.power_ready.store(true, Ordering::Relaxed);
|
||||
POWER_WAKER.wake();
|
||||
}
|
||||
}
|
||||
|
||||
impl VbusDetect for &SoftwareVbusDetect {
|
||||
fn is_usb_detected(&self) -> bool {
|
||||
self.usb_detected.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
|
||||
if self.power_ready.load(Ordering::Relaxed) {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if !self.usb_detected.load(Ordering::Relaxed) {
|
||||
Poll::Ready(Err(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ license = "MIT OR Apache-2.0"
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
msos-descriptor = ["embassy-usb/msos-descriptor"]
|
||||
nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net",
|
||||
"embassy-lora", "lorawan-device", "lorawan"]
|
||||
|
||||
@ -17,7 +16,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
|
||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
|
||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
|
||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true }
|
||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true }
|
||||
embedded-io = "0.4.0"
|
||||
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
|
||||
|
||||
@ -36,7 +35,3 @@ rand = { version = "0.8.4", default-features = false }
|
||||
embedded-storage = "0.3.0"
|
||||
usbd-hid = "0.6.0"
|
||||
serde = { version = "1.0.136", default-features = false }
|
||||
|
||||
[[bin]]
|
||||
name = "usb_serial_winusb"
|
||||
required-features = ["msos-descriptor"]
|
||||
|
@ -9,8 +9,9 @@ use embassy_executor::Spawner;
|
||||
use embassy_net::tcp::TcpSocket;
|
||||
use embassy_net::{Stack, StackResources};
|
||||
use embassy_nrf::rng::Rng;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{bind_interrupts, interrupt, pac, peripherals, rng};
|
||||
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
|
||||
use embassy_nrf::usb::Driver;
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb};
|
||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||
use embassy_usb::{Builder, Config, UsbDevice};
|
||||
@ -19,6 +20,8 @@ use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||
});
|
||||
|
||||
@ -60,9 +63,7 @@ async fn main(spawner: Spawner) {
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -86,6 +87,7 @@ async fn main(spawner: Spawner) {
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
);
|
||||
|
||||
// Our MAC addr.
|
||||
|
@ -10,8 +10,9 @@ use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_futures::select::{select, Either};
|
||||
use embassy_nrf::gpio::{Input, Pin, Pull};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
|
||||
use embassy_nrf::usb::Driver;
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::signal::Signal;
|
||||
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
|
||||
@ -20,6 +21,11 @@ use embassy_usb::{Builder, Config, Handler};
|
||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
});
|
||||
|
||||
static SUSPENDED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[embassy_executor::main]
|
||||
@ -32,9 +38,7 @@ async fn main(_spawner: Spawner) {
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -50,6 +54,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut device_descriptor = [0; 256];
|
||||
let mut config_descriptor = [0; 256];
|
||||
let mut bos_descriptor = [0; 256];
|
||||
let mut msos_descriptor = [0; 256];
|
||||
let mut control_buf = [0; 64];
|
||||
let request_handler = MyRequestHandler {};
|
||||
let mut device_handler = MyDeviceHandler::new();
|
||||
@ -62,6 +67,7 @@ async fn main(_spawner: Spawner) {
|
||||
&mut device_descriptor,
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut msos_descriptor,
|
||||
&mut control_buf,
|
||||
);
|
||||
|
||||
|
@ -7,8 +7,9 @@ use core::mem;
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
|
||||
use embassy_nrf::usb::Driver;
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
||||
use embassy_usb::control::OutResponse;
|
||||
@ -16,6 +17,11 @@ use embassy_usb::{Builder, Config};
|
||||
use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
@ -26,9 +32,7 @@ async fn main(_spawner: Spawner) {
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -43,6 +47,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut device_descriptor = [0; 256];
|
||||
let mut config_descriptor = [0; 256];
|
||||
let mut bos_descriptor = [0; 256];
|
||||
let mut msos_descriptor = [0; 256];
|
||||
let mut control_buf = [0; 64];
|
||||
let request_handler = MyRequestHandler {};
|
||||
|
||||
@ -54,6 +59,7 @@ async fn main(_spawner: Spawner) {
|
||||
&mut device_descriptor,
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut msos_descriptor,
|
||||
&mut control_buf,
|
||||
);
|
||||
|
||||
|
@ -7,13 +7,19 @@ use core::mem;
|
||||
use defmt::{info, panic};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
|
||||
use embassy_nrf::usb::{Driver, Instance};
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
use embassy_usb::{Builder, Config};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
@ -24,9 +30,7 @@ async fn main(_spawner: Spawner) {
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -48,6 +52,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut device_descriptor = [0; 256];
|
||||
let mut config_descriptor = [0; 256];
|
||||
let mut bos_descriptor = [0; 256];
|
||||
let mut msos_descriptor = [0; 256];
|
||||
let mut control_buf = [0; 64];
|
||||
|
||||
let mut state = State::new();
|
||||
@ -58,6 +63,7 @@ async fn main(_spawner: Spawner) {
|
||||
&mut device_descriptor,
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut msos_descriptor,
|
||||
&mut control_buf,
|
||||
);
|
||||
|
||||
|
@ -6,14 +6,29 @@ use core::mem;
|
||||
|
||||
use defmt::{info, panic, unwrap};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac, peripherals};
|
||||
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
|
||||
use embassy_nrf::usb::Driver;
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
use embassy_usb::{Builder, Config, UsbDevice};
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
});
|
||||
|
||||
macro_rules! singleton {
|
||||
($val:expr) => {{
|
||||
type T = impl Sized;
|
||||
static STATIC_CELL: StaticCell<T> = StaticCell::new();
|
||||
let (x,) = STATIC_CELL.init(($val,));
|
||||
x
|
||||
}};
|
||||
}
|
||||
|
||||
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
@ -39,10 +54,9 @@ async fn main(spawner: Spawner) {
|
||||
info!("Enabling ext hfosc...");
|
||||
clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -59,34 +73,21 @@ async fn main(spawner: Spawner) {
|
||||
config.device_protocol = 0x01;
|
||||
config.composite_with_iads = true;
|
||||
|
||||
struct Resources {
|
||||
device_descriptor: [u8; 256],
|
||||
config_descriptor: [u8; 256],
|
||||
bos_descriptor: [u8; 256],
|
||||
control_buf: [u8; 64],
|
||||
serial_state: State<'static>,
|
||||
}
|
||||
static RESOURCES: StaticCell<Resources> = StaticCell::new();
|
||||
let res = RESOURCES.init(Resources {
|
||||
device_descriptor: [0; 256],
|
||||
config_descriptor: [0; 256],
|
||||
bos_descriptor: [0; 256],
|
||||
control_buf: [0; 64],
|
||||
serial_state: State::new(),
|
||||
});
|
||||
let state = singleton!(State::new());
|
||||
|
||||
// Create embassy-usb DeviceBuilder using the driver and config.
|
||||
let mut builder = Builder::new(
|
||||
driver,
|
||||
config,
|
||||
&mut res.device_descriptor,
|
||||
&mut res.config_descriptor,
|
||||
&mut res.bos_descriptor,
|
||||
&mut res.control_buf,
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64);
|
||||
let class = CdcAcmClass::new(&mut builder, state, 64);
|
||||
|
||||
// Build the builder.
|
||||
let usb = builder.build();
|
||||
|
@ -7,8 +7,9 @@ use core::mem;
|
||||
use defmt::{info, panic};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
|
||||
use embassy_nrf::usb::{Driver, Instance};
|
||||
use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
use embassy_usb::msos::{self, windows_version};
|
||||
@ -16,6 +17,11 @@ use embassy_usb::types::InterfaceNumber;
|
||||
use embassy_usb::{Builder, Config};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
USBD => usb::InterruptHandler<peripherals::USBD>;
|
||||
POWER_CLOCK => usb::vbus_detect::InterruptHandler;
|
||||
});
|
||||
|
||||
// This is a randomly generated GUID to allow clients on Windows to find our device
|
||||
const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
|
||||
|
||||
@ -29,9 +35,7 @@ async fn main(_spawner: Spawner) {
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
|
Loading…
Reference in New Issue
Block a user