aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-05 22:36:53 +0100
committerDario Nieuwenhuis <[email protected]>2023-03-06 00:17:51 +0100
commit5249996d282e1ae08cea1593193e2fe6ca20880a (patch)
tree752b37a914066ceb602fbb821e56cfcda2d9912e
parent5913553cb1e95431665d3370dce8154a6869e434 (diff)
nrf/usb: switch to new interrupt binding, fix vbus detect on nrf53.
-rw-r--r--embassy-nrf/src/usb/mod.rs (renamed from embassy-nrf/src/usb.rs)234
-rw-r--r--embassy-nrf/src/usb/vbus_detect.rs177
-rw-r--r--examples/nrf52840/Cargo.toml7
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs12
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_serial.rs16
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs51
-rw-r--r--examples/nrf52840/src/bin/usb_serial_winusb.rs14
9 files changed, 300 insertions, 243 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb/mod.rs
index cd142f00f..56de511df 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb/mod.rs
@@ -2,10 +2,12 @@
2 2
3#![macro_use] 3#![macro_use]
4 4
5pub mod vbus_detect;
6
5use core::future::poll_fn; 7use core::future::poll_fn;
6use core::marker::PhantomData; 8use core::marker::PhantomData;
7use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
8use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; 10use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
9use core::task::Poll; 11use core::task::Poll;
10 12
11use cortex_m::peripheral::NVIC; 13use cortex_m::peripheral::NVIC;
@@ -15,7 +17,8 @@ use embassy_usb_driver as driver;
15use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; 17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
16use pac::usbd::RegisterBlock; 18use pac::usbd::RegisterBlock;
17 19
18use crate::interrupt::{Interrupt, InterruptExt}; 20use self::vbus_detect::VbusDetect;
21use crate::interrupt::{self, Interrupt, InterruptExt};
19use crate::util::slice_in_ram; 22use crate::util::slice_in_ram;
20use crate::{pac, Peripheral}; 23use crate::{pac, Peripheral};
21 24
@@ -26,185 +29,13 @@ static EP_IN_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
26static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8]; 29static EP_OUT_WAKERS: [AtomicWaker; 8] = [NEW_AW; 8];
27static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0); 30static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
28 31
29/// Trait for detecting USB VBUS power. 32/// Interrupt handler.
30/// 33pub struct InterruptHandler<T: Instance> {
31/// There are multiple ways to detect USB power. The behavior 34 _phantom: PhantomData<T>,
32/// here provides a hook into determining whether it is.
33pub trait VbusDetect {
34 /// Report whether power is detected.
35 ///
36 /// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
37 /// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
38 fn is_usb_detected(&self) -> bool;
39
40 /// Wait until USB power is ready.
41 ///
42 /// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
43 /// `USBPWRRDY` event from the `POWER` peripheral.
44 async fn wait_power_ready(&mut self) -> Result<(), ()>;
45}
46
47/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
48///
49/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
50/// to POWER. In that case, use [`VbusDetectSignal`].
51#[cfg(not(feature = "_nrf5340-app"))]
52pub struct HardwareVbusDetect {
53 _private: (),
54}
55
56static POWER_WAKER: AtomicWaker = NEW_AW;
57
58#[cfg(not(feature = "_nrf5340-app"))]
59impl HardwareVbusDetect {
60 /// Create a new `VbusDetectNative`.
61 pub fn new(power_irq: impl Interrupt) -> Self {
62 let regs = unsafe { &*pac::POWER::ptr() };
63
64 power_irq.set_handler(Self::on_interrupt);
65 power_irq.unpend();
66 power_irq.enable();
67
68 regs.intenset
69 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
70
71 Self { _private: () }
72 }
73
74 #[cfg(not(feature = "_nrf5340-app"))]
75 fn on_interrupt(_: *mut ()) {
76 let regs = unsafe { &*pac::POWER::ptr() };
77
78 if regs.events_usbdetected.read().bits() != 0 {
79 regs.events_usbdetected.reset();
80 BUS_WAKER.wake();
81 }
82
83 if regs.events_usbremoved.read().bits() != 0 {
84 regs.events_usbremoved.reset();
85 BUS_WAKER.wake();
86 POWER_WAKER.wake();
87 }
88
89 if regs.events_usbpwrrdy.read().bits() != 0 {
90 regs.events_usbpwrrdy.reset();
91 POWER_WAKER.wake();
92 }
93 }
94}
95
96#[cfg(not(feature = "_nrf5340-app"))]
97impl VbusDetect for HardwareVbusDetect {
98 fn is_usb_detected(&self) -> bool {
99 let regs = unsafe { &*pac::POWER::ptr() };
100 regs.usbregstatus.read().vbusdetect().is_vbus_present()
101 }
102
103 async fn wait_power_ready(&mut self) -> Result<(), ()> {
104 poll_fn(move |cx| {
105 POWER_WAKER.register(cx.waker());
106 let regs = unsafe { &*pac::POWER::ptr() };
107
108 if regs.usbregstatus.read().outputrdy().is_ready() {
109 Poll::Ready(Ok(()))
110 } else if !self.is_usb_detected() {
111 Poll::Ready(Err(()))
112 } else {
113 Poll::Pending
114 }
115 })
116 .await
117 }
118}
119
120/// Software-backed [`VbusDetect`] implementation.
121///
122/// This implementation does not interact with the hardware, it allows user code
123/// to notify the power events by calling functions instead.
124///
125/// This is suitable for use with the nRF softdevice, by calling the functions
126/// when the softdevice reports power-related events.
127pub struct SoftwareVbusDetect {
128 usb_detected: AtomicBool,
129 power_ready: AtomicBool,
130}
131
132impl SoftwareVbusDetect {
133 /// Create a new `SoftwareVbusDetect`.
134 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
135 BUS_WAKER.wake();
136
137 Self {
138 usb_detected: AtomicBool::new(usb_detected),
139 power_ready: AtomicBool::new(power_ready),
140 }
141 }
142
143 /// Report whether power was detected.
144 ///
145 /// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
146 pub fn detected(&self, detected: bool) {
147 self.usb_detected.store(detected, Ordering::Relaxed);
148 self.power_ready.store(false, Ordering::Relaxed);
149 BUS_WAKER.wake();
150 POWER_WAKER.wake();
151 }
152
153 /// Report when USB power is ready.
154 ///
155 /// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
156 pub fn ready(&self) {
157 self.power_ready.store(true, Ordering::Relaxed);
158 POWER_WAKER.wake();
159 }
160}
161
162impl VbusDetect for &SoftwareVbusDetect {
163 fn is_usb_detected(&self) -> bool {
164 self.usb_detected.load(Ordering::Relaxed)
165 }
166
167 async fn wait_power_ready(&mut self) -> Result<(), ()> {
168 poll_fn(move |cx| {
169 POWER_WAKER.register(cx.waker());
170
171 if self.power_ready.load(Ordering::Relaxed) {
172 Poll::Ready(Ok(()))
173 } else if !self.usb_detected.load(Ordering::Relaxed) {
174 Poll::Ready(Err(()))
175 } else {
176 Poll::Pending
177 }
178 })
179 .await
180 }
181} 35}
182 36
183/// USB driver. 37impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
184pub struct Driver<'d, T: Instance, P: VbusDetect> { 38 unsafe fn on_interrupt() {
185 _p: PeripheralRef<'d, T>,
186 alloc_in: Allocator,
187 alloc_out: Allocator,
188 usb_supply: P,
189}
190
191impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
192 /// Create a new USB driver.
193 pub fn new(usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd, usb_supply: P) -> Self {
194 into_ref!(usb, irq);
195 irq.set_handler(Self::on_interrupt);
196 irq.unpend();
197 irq.enable();
198
199 Self {
200 _p: usb,
201 alloc_in: Allocator::new(),
202 alloc_out: Allocator::new(),
203 usb_supply,
204 }
205 }
206
207 fn on_interrupt(_: *mut ()) {
208 let regs = T::regs(); 39 let regs = T::regs();
209 40
210 if regs.events_usbreset.read().bits() != 0 { 41 if regs.events_usbreset.read().bits() != 0 {
@@ -255,11 +86,40 @@ impl<'d, T: Instance, P: VbusDetect> Driver<'d, T, P> {
255 } 86 }
256} 87}
257 88
258impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P> { 89/// USB driver.
90pub struct Driver<'d, T: Instance, V: VbusDetect> {
91 _p: PeripheralRef<'d, T>,
92 alloc_in: Allocator,
93 alloc_out: Allocator,
94 vbus_detect: V,
95}
96
97impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> {
98 /// Create a new USB driver.
99 pub fn new(
100 usb: impl Peripheral<P = T> + 'd,
101 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102 vbus_detect: V,
103 ) -> Self {
104 into_ref!(usb);
105
106 unsafe { T::Interrupt::steal() }.unpend();
107 unsafe { T::Interrupt::steal() }.enable();
108
109 Self {
110 _p: usb,
111 alloc_in: Allocator::new(),
112 alloc_out: Allocator::new(),
113 vbus_detect,
114 }
115 }
116}
117
118impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V> {
259 type EndpointOut = Endpoint<'d, T, Out>; 119 type EndpointOut = Endpoint<'d, T, Out>;
260 type EndpointIn = Endpoint<'d, T, In>; 120 type EndpointIn = Endpoint<'d, T, In>;
261 type ControlPipe = ControlPipe<'d, T>; 121 type ControlPipe = ControlPipe<'d, T>;
262 type Bus = Bus<'d, T, P>; 122 type Bus = Bus<'d, T, V>;
263 123
264 fn alloc_endpoint_in( 124 fn alloc_endpoint_in(
265 &mut self, 125 &mut self,
@@ -298,7 +158,7 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
298 Bus { 158 Bus {
299 _p: unsafe { self._p.clone_unchecked() }, 159 _p: unsafe { self._p.clone_unchecked() },
300 power_available: false, 160 power_available: false,
301 usb_supply: self.usb_supply, 161 vbus_detect: self.vbus_detect,
302 }, 162 },
303 ControlPipe { 163 ControlPipe {
304 _p: self._p, 164 _p: self._p,
@@ -309,13 +169,13 @@ impl<'d, T: Instance, P: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, P
309} 169}
310 170
311/// USB bus. 171/// USB bus.
312pub struct Bus<'d, T: Instance, P: VbusDetect> { 172pub struct Bus<'d, T: Instance, V: VbusDetect> {
313 _p: PeripheralRef<'d, T>, 173 _p: PeripheralRef<'d, T>,
314 power_available: bool, 174 power_available: bool,
315 usb_supply: P, 175 vbus_detect: V,
316} 176}
317 177
318impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> { 178impl<'d, T: Instance, V: VbusDetect> driver::Bus for Bus<'d, T, V> {
319 async fn enable(&mut self) { 179 async fn enable(&mut self) {
320 let regs = T::regs(); 180 let regs = T::regs();
321 181
@@ -347,7 +207,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
347 w 207 w
348 }); 208 });
349 209
350 if self.usb_supply.wait_power_ready().await.is_ok() { 210 if self.vbus_detect.wait_power_ready().await.is_ok() {
351 // Enable the USB pullup, allowing enumeration. 211 // Enable the USB pullup, allowing enumeration.
352 regs.usbpullup.write(|w| w.connect().enabled()); 212 regs.usbpullup.write(|w| w.connect().enabled());
353 trace!("enabled"); 213 trace!("enabled");
@@ -406,7 +266,7 @@ impl<'d, T: Instance, P: VbusDetect> driver::Bus for Bus<'d, T, P> {
406 trace!("USB event: ready"); 266 trace!("USB event: ready");
407 } 267 }
408 268
409 if self.usb_supply.is_usb_detected() != self.power_available { 269 if self.vbus_detect.is_usb_detected() != self.power_available {
410 self.power_available = !self.power_available; 270 self.power_available = !self.power_available;
411 if self.power_available { 271 if self.power_available {
412 trace!("Power event: available"); 272 trace!("Power event: available");
diff --git a/embassy-nrf/src/usb/vbus_detect.rs b/embassy-nrf/src/usb/vbus_detect.rs
new file mode 100644
index 000000000..cecd4c595
--- /dev/null
+++ b/embassy-nrf/src/usb/vbus_detect.rs
@@ -0,0 +1,177 @@
1//! Trait and implementations for performing VBUS detection.
2
3use core::future::poll_fn;
4use core::sync::atomic::{AtomicBool, Ordering};
5use core::task::Poll;
6
7use embassy_sync::waitqueue::AtomicWaker;
8
9use super::BUS_WAKER;
10use crate::interrupt::{self, Interrupt, InterruptExt};
11use crate::pac;
12
13/// Trait for detecting USB VBUS power.
14///
15/// There are multiple ways to detect USB power. The behavior
16/// here provides a hook into determining whether it is.
17pub trait VbusDetect {
18 /// Report whether power is detected.
19 ///
20 /// This is indicated by the `USBREGSTATUS.VBUSDETECT` register, or the
21 /// `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
22 fn is_usb_detected(&self) -> bool;
23
24 /// Wait until USB power is ready.
25 ///
26 /// USB power ready is indicated by the `USBREGSTATUS.OUTPUTRDY` register, or the
27 /// `USBPWRRDY` event from the `POWER` peripheral.
28 async fn wait_power_ready(&mut self) -> Result<(), ()>;
29}
30
31#[cfg(not(feature = "_nrf5340"))]
32type UsbRegIrq = interrupt::POWER_CLOCK;
33#[cfg(feature = "_nrf5340")]
34type UsbRegIrq = interrupt::USBREGULATOR;
35
36#[cfg(not(feature = "_nrf5340"))]
37type UsbRegPeri = pac::POWER;
38#[cfg(feature = "_nrf5340")]
39type UsbRegPeri = pac::USBREGULATOR;
40
41/// Interrupt handler.
42pub struct InterruptHandler {
43 _private: (),
44}
45
46impl interrupt::Handler<UsbRegIrq> for InterruptHandler {
47 unsafe fn on_interrupt() {
48 let regs = unsafe { &*UsbRegPeri::ptr() };
49
50 if regs.events_usbdetected.read().bits() != 0 {
51 regs.events_usbdetected.reset();
52 BUS_WAKER.wake();
53 }
54
55 if regs.events_usbremoved.read().bits() != 0 {
56 regs.events_usbremoved.reset();
57 BUS_WAKER.wake();
58 POWER_WAKER.wake();
59 }
60
61 if regs.events_usbpwrrdy.read().bits() != 0 {
62 regs.events_usbpwrrdy.reset();
63 POWER_WAKER.wake();
64 }
65 }
66}
67
68/// [`VbusDetect`] implementation using the native hardware POWER peripheral.
69///
70/// Unsuitable for usage with the nRF softdevice, since it reserves exclusive acces
71/// to POWER. In that case, use [`VbusDetectSignal`].
72pub struct HardwareVbusDetect {
73 _private: (),
74}
75
76static POWER_WAKER: AtomicWaker = AtomicWaker::new();
77
78impl HardwareVbusDetect {
79 /// Create a new `VbusDetectNative`.
80 pub fn new(_irq: impl interrupt::Binding<UsbRegIrq, InterruptHandler> + 'static) -> Self {
81 let regs = unsafe { &*UsbRegPeri::ptr() };
82
83 unsafe { UsbRegIrq::steal() }.unpend();
84 unsafe { UsbRegIrq::steal() }.enable();
85
86 regs.intenset
87 .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set());
88
89 Self { _private: () }
90 }
91}
92
93impl VbusDetect for HardwareVbusDetect {
94 fn is_usb_detected(&self) -> bool {
95 let regs = unsafe { &*UsbRegPeri::ptr() };
96 regs.usbregstatus.read().vbusdetect().is_vbus_present()
97 }
98
99 async fn wait_power_ready(&mut self) -> Result<(), ()> {
100 poll_fn(move |cx| {
101 POWER_WAKER.register(cx.waker());
102 let regs = unsafe { &*UsbRegPeri::ptr() };
103
104 if regs.usbregstatus.read().outputrdy().is_ready() {
105 Poll::Ready(Ok(()))
106 } else if !self.is_usb_detected() {
107 Poll::Ready(Err(()))
108 } else {
109 Poll::Pending
110 }
111 })
112 .await
113 }
114}
115
116/// Software-backed [`VbusDetect`] implementation.
117///
118/// This implementation does not interact with the hardware, it allows user code
119/// to notify the power events by calling functions instead.
120///
121/// This is suitable for use with the nRF softdevice, by calling the functions
122/// when the softdevice reports power-related events.
123pub struct SoftwareVbusDetect {
124 usb_detected: AtomicBool,
125 power_ready: AtomicBool,
126}
127
128impl SoftwareVbusDetect {
129 /// Create a new `SoftwareVbusDetect`.
130 pub fn new(usb_detected: bool, power_ready: bool) -> Self {
131 BUS_WAKER.wake();
132
133 Self {
134 usb_detected: AtomicBool::new(usb_detected),
135 power_ready: AtomicBool::new(power_ready),
136 }
137 }
138
139 /// Report whether power was detected.
140 ///
141 /// Equivalent to the `USBDETECTED`, `USBREMOVED` events from the `POWER` peripheral.
142 pub fn detected(&self, detected: bool) {
143 self.usb_detected.store(detected, Ordering::Relaxed);
144 self.power_ready.store(false, Ordering::Relaxed);
145 BUS_WAKER.wake();
146 POWER_WAKER.wake();
147 }
148
149 /// Report when USB power is ready.
150 ///
151 /// Equivalent to the `USBPWRRDY` event from the `POWER` peripheral.
152 pub fn ready(&self) {
153 self.power_ready.store(true, Ordering::Relaxed);
154 POWER_WAKER.wake();
155 }
156}
157
158impl VbusDetect for &SoftwareVbusDetect {
159 fn is_usb_detected(&self) -> bool {
160 self.usb_detected.load(Ordering::Relaxed)
161 }
162
163 async fn wait_power_ready(&mut self) -> Result<(), ()> {
164 poll_fn(move |cx| {
165 POWER_WAKER.register(cx.waker());
166
167 if self.power_ready.load(Ordering::Relaxed) {
168 Poll::Ready(Ok(()))
169 } else if !self.usb_detected.load(Ordering::Relaxed) {
170 Poll::Ready(Err(()))
171 } else {
172 Poll::Pending
173 }
174 })
175 .await
176 }
177}
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index cfdda076e..cc88d92c7 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -6,7 +6,6 @@ license = "MIT OR Apache-2.0"
6 6
7[features] 7[features]
8default = ["nightly"] 8default = ["nightly"]
9msos-descriptor = ["embassy-usb/msos-descriptor"]
10nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net", 9nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net",
11 "embassy-lora", "lorawan-device", "lorawan"] 10 "embassy-lora", "lorawan-device", "lorawan"]
12 11
@@ -17,7 +16,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
17embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
18embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
19embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } 18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
20embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } 19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true }
21embedded-io = "0.4.0" 20embedded-io = "0.4.0"
22embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } 21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
23 22
@@ -36,7 +35,3 @@ rand = { version = "0.8.4", default-features = false }
36embedded-storage = "0.3.0" 35embedded-storage = "0.3.0"
37usbd-hid = "0.6.0" 36usbd-hid = "0.6.0"
38serde = { version = "1.0.136", default-features = false } 37serde = { version = "1.0.136", default-features = false }
39
40[[bin]]
41name = "usb_serial_winusb"
42required-features = ["msos-descriptor"]
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index 083a1cbb0..b8a72313a 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -9,8 +9,9 @@ use embassy_executor::Spawner;
9use embassy_net::tcp::TcpSocket; 9use embassy_net::tcp::TcpSocket;
10use embassy_net::{Stack, StackResources}; 10use embassy_net::{Stack, StackResources};
11use embassy_nrf::rng::Rng; 11use embassy_nrf::rng::Rng;
12use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 12use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
13use embassy_nrf::{bind_interrupts, interrupt, pac, peripherals, rng}; 13use embassy_nrf::usb::Driver;
14use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb};
14use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 15use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
15use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 16use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
16use embassy_usb::{Builder, Config, UsbDevice}; 17use embassy_usb::{Builder, Config, UsbDevice};
@@ -19,6 +20,8 @@ use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
20 21
21bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
23 USBD => usb::InterruptHandler<peripherals::USBD>;
24 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
22 RNG => rng::InterruptHandler<peripherals::RNG>; 25 RNG => rng::InterruptHandler<peripherals::RNG>;
23}); 26});
24 27
@@ -60,9 +63,7 @@ async fn main(spawner: Spawner) {
60 while clock.events_hfclkstarted.read().bits() != 1 {} 63 while clock.events_hfclkstarted.read().bits() != 1 {}
61 64
62 // Create the driver, from the HAL. 65 // Create the driver, from the HAL.
63 let irq = interrupt::take!(USBD); 66 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
64 let power_irq = interrupt::take!(POWER_CLOCK);
65 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
66 67
67 // Create embassy-usb Config 68 // Create embassy-usb Config
68 let mut config = Config::new(0xc0de, 0xcafe); 69 let mut config = Config::new(0xc0de, 0xcafe);
@@ -86,6 +87,7 @@ async fn main(spawner: Spawner) {
86 &mut singleton!([0; 256])[..], 87 &mut singleton!([0; 256])[..],
87 &mut singleton!([0; 256])[..], 88 &mut singleton!([0; 256])[..],
88 &mut singleton!([0; 128])[..], 89 &mut singleton!([0; 128])[..],
90 &mut singleton!([0; 128])[..],
89 ); 91 );
90 92
91 // Our MAC addr. 93 // Our MAC addr.
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
index 3d8a114cd..7ccd2946a 100644
--- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
@@ -10,8 +10,9 @@ use embassy_executor::Spawner;
10use embassy_futures::join::join; 10use embassy_futures::join::join;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_nrf::gpio::{Input, Pin, Pull}; 12use embassy_nrf::gpio::{Input, Pin, Pull};
13use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 13use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
14use embassy_nrf::{interrupt, pac}; 14use embassy_nrf::usb::Driver;
15use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16use embassy_sync::signal::Signal; 17use embassy_sync::signal::Signal;
17use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 18use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
@@ -20,6 +21,11 @@ use embassy_usb::{Builder, Config, Handler};
20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 21use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
21use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
22 23
24bind_interrupts!(struct Irqs {
25 USBD => usb::InterruptHandler<peripherals::USBD>;
26 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
27});
28
23static SUSPENDED: AtomicBool = AtomicBool::new(false); 29static SUSPENDED: AtomicBool = AtomicBool::new(false);
24 30
25#[embassy_executor::main] 31#[embassy_executor::main]
@@ -32,9 +38,7 @@ async fn main(_spawner: Spawner) {
32 while clock.events_hfclkstarted.read().bits() != 1 {} 38 while clock.events_hfclkstarted.read().bits() != 1 {}
33 39
34 // Create the driver, from the HAL. 40 // Create the driver, from the HAL.
35 let irq = interrupt::take!(USBD); 41 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
36 let power_irq = interrupt::take!(POWER_CLOCK);
37 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
38 42
39 // Create embassy-usb Config 43 // Create embassy-usb Config
40 let mut config = Config::new(0xc0de, 0xcafe); 44 let mut config = Config::new(0xc0de, 0xcafe);
@@ -50,6 +54,7 @@ async fn main(_spawner: Spawner) {
50 let mut device_descriptor = [0; 256]; 54 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 55 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 56 let mut bos_descriptor = [0; 256];
57 let mut msos_descriptor = [0; 256];
53 let mut control_buf = [0; 64]; 58 let mut control_buf = [0; 64];
54 let request_handler = MyRequestHandler {}; 59 let request_handler = MyRequestHandler {};
55 let mut device_handler = MyDeviceHandler::new(); 60 let mut device_handler = MyDeviceHandler::new();
@@ -62,6 +67,7 @@ async fn main(_spawner: Spawner) {
62 &mut device_descriptor, 67 &mut device_descriptor,
63 &mut config_descriptor, 68 &mut config_descriptor,
64 &mut bos_descriptor, 69 &mut bos_descriptor,
70 &mut msos_descriptor,
65 &mut control_buf, 71 &mut control_buf,
66 ); 72 );
67 73
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index d7c9d55b7..edf634a5e 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -7,8 +7,9 @@ use core::mem;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::Driver;
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
13use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
14use embassy_usb::control::OutResponse; 15use embassy_usb::control::OutResponse;
@@ -16,6 +17,11 @@ use embassy_usb::{Builder, Config};
16use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 17use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
17use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
18 19
20bind_interrupts!(struct Irqs {
21 USBD => usb::InterruptHandler<peripherals::USBD>;
22 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
23});
24
19#[embassy_executor::main] 25#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 26async fn main(_spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default()); 27 let p = embassy_nrf::init(Default::default());
@@ -26,9 +32,7 @@ async fn main(_spawner: Spawner) {
26 while clock.events_hfclkstarted.read().bits() != 1 {} 32 while clock.events_hfclkstarted.read().bits() != 1 {}
27 33
28 // Create the driver, from the HAL. 34 // Create the driver, from the HAL.
29 let irq = interrupt::take!(USBD); 35 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
30 let power_irq = interrupt::take!(POWER_CLOCK);
31 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
32 36
33 // Create embassy-usb Config 37 // Create embassy-usb Config
34 let mut config = Config::new(0xc0de, 0xcafe); 38 let mut config = Config::new(0xc0de, 0xcafe);
@@ -43,6 +47,7 @@ async fn main(_spawner: Spawner) {
43 let mut device_descriptor = [0; 256]; 47 let mut device_descriptor = [0; 256];
44 let mut config_descriptor = [0; 256]; 48 let mut config_descriptor = [0; 256];
45 let mut bos_descriptor = [0; 256]; 49 let mut bos_descriptor = [0; 256];
50 let mut msos_descriptor = [0; 256];
46 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
47 let request_handler = MyRequestHandler {}; 52 let request_handler = MyRequestHandler {};
48 53
@@ -54,6 +59,7 @@ async fn main(_spawner: Spawner) {
54 &mut device_descriptor, 59 &mut device_descriptor,
55 &mut config_descriptor, 60 &mut config_descriptor,
56 &mut bos_descriptor, 61 &mut bos_descriptor,
62 &mut msos_descriptor,
57 &mut control_buf, 63 &mut control_buf,
58 ); 64 );
59 65
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs
index 102d7ea60..9727a4f57 100644
--- a/examples/nrf52840/src/bin/usb_serial.rs
+++ b/examples/nrf52840/src/bin/usb_serial.rs
@@ -7,13 +7,19 @@ use core::mem;
7use defmt::{info, panic}; 7use defmt::{info, panic};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; 10use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::{Driver, Instance};
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::{Builder, Config}; 15use embassy_usb::{Builder, Config};
15use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
16 17
18bind_interrupts!(struct Irqs {
19 USBD => usb::InterruptHandler<peripherals::USBD>;
20 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
21});
22
17#[embassy_executor::main] 23#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
19 let p = embassy_nrf::init(Default::default()); 25 let p = embassy_nrf::init(Default::default());
@@ -24,9 +30,7 @@ async fn main(_spawner: Spawner) {
24 while clock.events_hfclkstarted.read().bits() != 1 {} 30 while clock.events_hfclkstarted.read().bits() != 1 {}
25 31
26 // Create the driver, from the HAL. 32 // Create the driver, from the HAL.
27 let irq = interrupt::take!(USBD); 33 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
28 let power_irq = interrupt::take!(POWER_CLOCK);
29 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
30 34
31 // Create embassy-usb Config 35 // Create embassy-usb Config
32 let mut config = Config::new(0xc0de, 0xcafe); 36 let mut config = Config::new(0xc0de, 0xcafe);
@@ -48,6 +52,7 @@ async fn main(_spawner: Spawner) {
48 let mut device_descriptor = [0; 256]; 52 let mut device_descriptor = [0; 256];
49 let mut config_descriptor = [0; 256]; 53 let mut config_descriptor = [0; 256];
50 let mut bos_descriptor = [0; 256]; 54 let mut bos_descriptor = [0; 256];
55 let mut msos_descriptor = [0; 256];
51 let mut control_buf = [0; 64]; 56 let mut control_buf = [0; 64];
52 57
53 let mut state = State::new(); 58 let mut state = State::new();
@@ -58,6 +63,7 @@ async fn main(_spawner: Spawner) {
58 &mut device_descriptor, 63 &mut device_descriptor,
59 &mut config_descriptor, 64 &mut config_descriptor,
60 &mut bos_descriptor, 65 &mut bos_descriptor,
66 &mut msos_descriptor,
61 &mut control_buf, 67 &mut control_buf,
62 ); 68 );
63 69
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index 558d4ba60..6da2c2a2f 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -6,14 +6,29 @@ use core::mem;
6 6
7use defmt::{info, panic, unwrap}; 7use defmt::{info, panic, unwrap};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::usb::{Driver, HardwareVbusDetect}; 9use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
10use embassy_nrf::{interrupt, pac, peripherals}; 10use embassy_nrf::usb::Driver;
11use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 12use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 13use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config, UsbDevice}; 14use embassy_usb::{Builder, Config, UsbDevice};
14use static_cell::StaticCell; 15use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
16 17
18bind_interrupts!(struct Irqs {
19 USBD => usb::InterruptHandler<peripherals::USBD>;
20 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
21});
22
23macro_rules! singleton {
24 ($val:expr) => {{
25 type T = impl Sized;
26 static STATIC_CELL: StaticCell<T> = StaticCell::new();
27 let (x,) = STATIC_CELL.init(($val,));
28 x
29 }};
30}
31
17type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; 32type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
18 33
19#[embassy_executor::task] 34#[embassy_executor::task]
@@ -39,10 +54,9 @@ async fn main(spawner: Spawner) {
39 info!("Enabling ext hfosc..."); 54 info!("Enabling ext hfosc...");
40 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 55 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
41 while clock.events_hfclkstarted.read().bits() != 1 {} 56 while clock.events_hfclkstarted.read().bits() != 1 {}
57
42 // Create the driver, from the HAL. 58 // Create the driver, from the HAL.
43 let irq = interrupt::take!(USBD); 59 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
44 let power_irq = interrupt::take!(POWER_CLOCK);
45 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
46 60
47 // Create embassy-usb Config 61 // Create embassy-usb Config
48 let mut config = Config::new(0xc0de, 0xcafe); 62 let mut config = Config::new(0xc0de, 0xcafe);
@@ -59,34 +73,21 @@ async fn main(spawner: Spawner) {
59 config.device_protocol = 0x01; 73 config.device_protocol = 0x01;
60 config.composite_with_iads = true; 74 config.composite_with_iads = true;
61 75
62 struct Resources { 76 let state = singleton!(State::new());
63 device_descriptor: [u8; 256],
64 config_descriptor: [u8; 256],
65 bos_descriptor: [u8; 256],
66 control_buf: [u8; 64],
67 serial_state: State<'static>,
68 }
69 static RESOURCES: StaticCell<Resources> = StaticCell::new();
70 let res = RESOURCES.init(Resources {
71 device_descriptor: [0; 256],
72 config_descriptor: [0; 256],
73 bos_descriptor: [0; 256],
74 control_buf: [0; 64],
75 serial_state: State::new(),
76 });
77 77
78 // Create embassy-usb DeviceBuilder using the driver and config. 78 // Create embassy-usb DeviceBuilder using the driver and config.
79 let mut builder = Builder::new( 79 let mut builder = Builder::new(
80 driver, 80 driver,
81 config, 81 config,
82 &mut res.device_descriptor, 82 &mut singleton!([0; 256])[..],
83 &mut res.config_descriptor, 83 &mut singleton!([0; 256])[..],
84 &mut res.bos_descriptor, 84 &mut singleton!([0; 256])[..],
85 &mut res.control_buf, 85 &mut singleton!([0; 128])[..],
86 &mut singleton!([0; 128])[..],
86 ); 87 );
87 88
88 // Create classes on the builder. 89 // Create classes on the builder.
89 let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64); 90 let class = CdcAcmClass::new(&mut builder, state, 64);
90 91
91 // Build the builder. 92 // Build the builder.
92 let usb = builder.build(); 93 let usb = builder.build();
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs
index 6561fc3b4..6e4f71a48 100644
--- a/examples/nrf52840/src/bin/usb_serial_winusb.rs
+++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs
@@ -7,8 +7,9 @@ use core::mem;
7use defmt::{info, panic}; 7use defmt::{info, panic};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect}; 10use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::usb::{Driver, Instance};
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::msos::{self, windows_version}; 15use embassy_usb::msos::{self, windows_version};
@@ -16,6 +17,11 @@ use embassy_usb::types::InterfaceNumber;
16use embassy_usb::{Builder, Config}; 17use embassy_usb::{Builder, Config};
17use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
18 19
20bind_interrupts!(struct Irqs {
21 USBD => usb::InterruptHandler<peripherals::USBD>;
22 POWER_CLOCK => usb::vbus_detect::InterruptHandler;
23});
24
19// This is a randomly generated GUID to allow clients on Windows to find our device 25// This is a randomly generated GUID to allow clients on Windows to find our device
20const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; 26const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
21 27
@@ -29,9 +35,7 @@ async fn main(_spawner: Spawner) {
29 while clock.events_hfclkstarted.read().bits() != 1 {} 35 while clock.events_hfclkstarted.read().bits() != 1 {}
30 36
31 // Create the driver, from the HAL. 37 // Create the driver, from the HAL.
32 let irq = interrupt::take!(USBD); 38 let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
33 let power_irq = interrupt::take!(POWER_CLOCK);
34 let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
35 39
36 // Create embassy-usb Config 40 // Create embassy-usb Config
37 let mut config = Config::new(0xc0de, 0xcafe); 41 let mut config = Config::new(0xc0de, 0xcafe);