aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-11 00:01:41 +0000
committerGitHub <[email protected]>2022-07-11 00:01:41 +0000
commit9753f767946d79c5987c166e513150aca98ec042 (patch)
treecafaeeaa7714fff7271818b3eea976f71f382739 /examples
parent163cf1f335ed11011a68c2a90c447ece121fc22f (diff)
parent8785fbc6f1a1227115d3ffa6a6c19035bed6ef8c (diff)
Merge #810
810: Takes care of power for nRF USB devices r=Dirbaio a=huntc Modifies the usb-serial example to illustrate how to setup USB for situations where the USB power can be detected and removed. Gaps: ~~* No support for the nrf-softdevices as yet, although this should be possible via another constructor.~~ * No support for the nrf5340, although this should be possible via USBREG. The change is tested and appears to work. Some notes: * There's an existing field named self_powered as a UsbDevice field. It doesn't ever appear to get set. I'm wondering if this field is intended to signal that a device has the nRF VBUS power situation or not. I'm not presently using it. * The new PowerDetected event is generated on the bus initially in situations where just new is used i.e. without power management, including on STM. We can therefore rely on this event always being generated. Old description: ~~EnabledUsbDevice is a wrapper around the `UsbDevice` where its enablement is also subject to external events, such as `POWER` events for nRF. It is introduced generically to support other platforms should they also require external signaling for enablement.~~ Co-authored-by: huntc <[email protected]>
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf/src/bin/usb_ethernet.rs12
-rw-r--r--examples/nrf/src/bin/usb_hid_keyboard.rs71
-rw-r--r--examples/nrf/src/bin/usb_hid_mouse.rs10
-rw-r--r--examples/nrf/src/bin/usb_serial.rs14
-rw-r--r--examples/nrf/src/bin/usb_serial_multitask.rs13
5 files changed, 25 insertions, 95 deletions
diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs
index a20321fe8..e57cdaf63 100644
--- a/examples/nrf/src/bin/usb_ethernet.rs
+++ b/examples/nrf/src/bin/usb_ethernet.rs
@@ -15,14 +15,14 @@ use embassy::util::Forever;
15use embassy_net::tcp::TcpSocket; 15use embassy_net::tcp::TcpSocket;
16use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; 16use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources};
17use embassy_nrf::rng::Rng; 17use embassy_nrf::rng::Rng;
18use embassy_nrf::usb::Driver; 18use embassy_nrf::usb::{Driver, PowerUsb};
19use embassy_nrf::{interrupt, pac, peripherals, Peripherals}; 19use embassy_nrf::{interrupt, pac, peripherals, Peripherals};
20use embassy_usb::{Builder, Config, UsbDevice}; 20use embassy_usb::{Builder, Config, UsbDevice};
21use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; 21use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
22use embedded_io::asynch::{Read, Write}; 22use embedded_io::asynch::{Read, Write};
23use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
24 24
25type MyDriver = Driver<'static, peripherals::USBD>; 25type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
26 26
27macro_rules! forever { 27macro_rules! forever {
28 ($val:expr) => {{ 28 ($val:expr) => {{
@@ -84,19 +84,15 @@ async fn net_task(stack: &'static Stack<Device>) -> ! {
84#[embassy::main] 84#[embassy::main]
85async fn main(spawner: Spawner, p: Peripherals) { 85async fn main(spawner: Spawner, p: Peripherals) {
86 let clock: pac::CLOCK = unsafe { mem::transmute(()) }; 86 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
87 let power: pac::POWER = unsafe { mem::transmute(()) };
88 87
89 info!("Enabling ext hfosc..."); 88 info!("Enabling ext hfosc...");
90 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 89 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
91 while clock.events_hfclkstarted.read().bits() != 1 {} 90 while clock.events_hfclkstarted.read().bits() != 1 {}
92 91
93 info!("Waiting for vbus...");
94 while !power.usbregstatus.read().vbusdetect().is_vbus_present() {}
95 info!("vbus OK");
96
97 // Create the driver, from the HAL. 92 // Create the driver, from the HAL.
98 let irq = interrupt::take!(USBD); 93 let irq = interrupt::take!(USBD);
99 let driver = Driver::new(p.USBD, irq); 94 let power_irq = interrupt::take!(POWER_CLOCK);
95 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
100 96
101 // Create embassy-usb Config 97 // Create embassy-usb Config
102 let mut config = Config::new(0xc0de, 0xcafe); 98 let mut config = Config::new(0xc0de, 0xcafe);
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs
index 97ec861d8..539ae6f16 100644
--- a/examples/nrf/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf/src/bin/usb_hid_keyboard.rs
@@ -10,10 +10,9 @@ use defmt::*;
10use embassy::channel::signal::Signal; 10use embassy::channel::signal::Signal;
11use embassy::executor::Spawner; 11use embassy::executor::Spawner;
12use embassy::time::Duration; 12use embassy::time::Duration;
13use embassy::util::{select, select3, Either, Either3}; 13use embassy::util::{select, Either};
14use embassy_nrf::gpio::{Input, Pin, Pull}; 14use embassy_nrf::gpio::{Input, Pin, Pull};
15use embassy_nrf::interrupt::InterruptExt; 15use embassy_nrf::usb::{Driver, PowerUsb};
16use embassy_nrf::usb::Driver;
17use embassy_nrf::{interrupt, pac, Peripherals}; 16use embassy_nrf::{interrupt, pac, Peripherals};
18use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
19use embassy_usb::{Builder, Config, DeviceStateHandler}; 18use embassy_usb::{Builder, Config, DeviceStateHandler};
@@ -22,29 +21,11 @@ use futures::future::join;
22use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 21use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
25static ENABLE_USB: Signal<bool> = Signal::new();
26static SUSPENDED: AtomicBool = AtomicBool::new(false); 24static SUSPENDED: AtomicBool = AtomicBool::new(false);
27 25
28fn on_power_interrupt(_: *mut ()) {
29 let regs = unsafe { &*pac::POWER::ptr() };
30
31 if regs.events_usbdetected.read().bits() != 0 {
32 regs.events_usbdetected.reset();
33 info!("Vbus detected, enabling USB...");
34 ENABLE_USB.signal(true);
35 }
36
37 if regs.events_usbremoved.read().bits() != 0 {
38 regs.events_usbremoved.reset();
39 info!("Vbus removed, disabling USB...");
40 ENABLE_USB.signal(false);
41 }
42}
43
44#[embassy::main] 26#[embassy::main]
45async fn main(_spawner: Spawner, p: Peripherals) { 27async fn main(_spawner: Spawner, p: Peripherals) {
46 let clock: pac::CLOCK = unsafe { mem::transmute(()) }; 28 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
47 let power: pac::POWER = unsafe { mem::transmute(()) };
48 29
49 info!("Enabling ext hfosc..."); 30 info!("Enabling ext hfosc...");
50 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 31 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
@@ -52,7 +33,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
52 33
53 // Create the driver, from the HAL. 34 // Create the driver, from the HAL.
54 let irq = interrupt::take!(USBD); 35 let irq = interrupt::take!(USBD);
55 let driver = Driver::new(p.USBD, irq); 36 let power_irq = interrupt::take!(POWER_CLOCK);
37 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
56 38
57 // Create embassy-usb Config 39 // Create embassy-usb Config
58 let mut config = Config::new(0xc0de, 0xcafe); 40 let mut config = Config::new(0xc0de, 0xcafe);
@@ -100,31 +82,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
100 82
101 // Run the USB device. 83 // Run the USB device.
102 let usb_fut = async { 84 let usb_fut = async {
103 enable_command().await;
104 loop { 85 loop {
105 match select(usb.run_until_suspend(), ENABLE_USB.wait()).await { 86 usb.run_until_suspend().await;
106 Either::First(_) => {} 87 match select(usb.wait_resume(), remote_wakeup.wait()).await {
107 Either::Second(enable) => { 88 Either::First(_) => (),
108 if enable { 89 Either::Second(_) => unwrap!(usb.remote_wakeup().await),
109 warn!("Enable when already enabled!");
110 } else {
111 usb.disable().await;
112 enable_command().await;
113 }
114 }
115 }
116
117 match select3(usb.wait_resume(), ENABLE_USB.wait(), remote_wakeup.wait()).await {
118 Either3::First(_) => (),
119 Either3::Second(enable) => {
120 if enable {
121 warn!("Enable when already enabled!");
122 } else {
123 usb.disable().await;
124 enable_command().await;
125 }
126 }
127 Either3::Third(_) => unwrap!(usb.remote_wakeup().await),
128 } 90 }
129 } 91 }
130 }; 92 };
@@ -174,28 +136,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
174 reader.run(false, &request_handler).await; 136 reader.run(false, &request_handler).await;
175 }; 137 };
176 138
177 let power_irq = interrupt::take!(POWER_CLOCK);
178 power_irq.set_handler(on_power_interrupt);
179 power_irq.unpend();
180 power_irq.enable();
181
182 power.intenset.write(|w| w.usbdetected().set().usbremoved().set());
183
184 // Run everything concurrently. 139 // Run everything concurrently.
185 // If we had made everything `'static` above instead, we could do this using separate tasks instead. 140 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
186 join(usb_fut, join(in_fut, out_fut)).await; 141 join(usb_fut, join(in_fut, out_fut)).await;
187} 142}
188 143
189async fn enable_command() {
190 loop {
191 if ENABLE_USB.wait().await {
192 break;
193 } else {
194 warn!("Received disable signal when already disabled!");
195 }
196 }
197}
198
199struct MyRequestHandler {} 144struct MyRequestHandler {}
200 145
201impl RequestHandler for MyRequestHandler { 146impl RequestHandler for MyRequestHandler {
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs
index 9c44e5cc8..516e7ea95 100644
--- a/examples/nrf/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf/src/bin/usb_hid_mouse.rs
@@ -8,7 +8,7 @@ use core::mem;
8use defmt::*; 8use defmt::*;
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer}; 10use embassy::time::{Duration, Timer};
11use embassy_nrf::usb::Driver; 11use embassy_nrf::usb::{Driver, PowerUsb};
12use embassy_nrf::{interrupt, pac, Peripherals}; 12use embassy_nrf::{interrupt, pac, Peripherals};
13use embassy_usb::control::OutResponse; 13use embassy_usb::control::OutResponse;
14use embassy_usb::{Builder, Config}; 14use embassy_usb::{Builder, Config};
@@ -20,19 +20,15 @@ use {defmt_rtt as _, panic_probe as _};
20#[embassy::main] 20#[embassy::main]
21async fn main(_spawner: Spawner, p: Peripherals) { 21async fn main(_spawner: Spawner, p: Peripherals) {
22 let clock: pac::CLOCK = unsafe { mem::transmute(()) }; 22 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
23 let power: pac::POWER = unsafe { mem::transmute(()) };
24 23
25 info!("Enabling ext hfosc..."); 24 info!("Enabling ext hfosc...");
26 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 25 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
27 while clock.events_hfclkstarted.read().bits() != 1 {} 26 while clock.events_hfclkstarted.read().bits() != 1 {}
28 27
29 info!("Waiting for vbus...");
30 while !power.usbregstatus.read().vbusdetect().is_vbus_present() {}
31 info!("vbus OK");
32
33 // Create the driver, from the HAL. 28 // Create the driver, from the HAL.
34 let irq = interrupt::take!(USBD); 29 let irq = interrupt::take!(USBD);
35 let driver = Driver::new(p.USBD, irq); 30 let power_irq = interrupt::take!(POWER_CLOCK);
31 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
36 32
37 // Create embassy-usb Config 33 // Create embassy-usb Config
38 let mut config = Config::new(0xc0de, 0xcafe); 34 let mut config = Config::new(0xc0de, 0xcafe);
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs
index f108db46d..d2200dc5d 100644
--- a/examples/nrf/src/bin/usb_serial.rs
+++ b/examples/nrf/src/bin/usb_serial.rs
@@ -7,7 +7,7 @@ use core::mem;
7 7
8use defmt::{info, panic}; 8use defmt::{info, panic};
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy_nrf::usb::{Driver, Instance}; 10use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply};
11use embassy_nrf::{interrupt, pac, Peripherals}; 11use embassy_nrf::{interrupt, pac, Peripherals};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config}; 13use embassy_usb::{Builder, Config};
@@ -18,19 +18,15 @@ use {defmt_rtt as _, panic_probe as _};
18#[embassy::main] 18#[embassy::main]
19async fn main(_spawner: Spawner, p: Peripherals) { 19async fn main(_spawner: Spawner, p: Peripherals) {
20 let clock: pac::CLOCK = unsafe { mem::transmute(()) }; 20 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
21 let power: pac::POWER = unsafe { mem::transmute(()) };
22 21
23 info!("Enabling ext hfosc..."); 22 info!("Enabling ext hfosc...");
24 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 23 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
25 while clock.events_hfclkstarted.read().bits() != 1 {} 24 while clock.events_hfclkstarted.read().bits() != 1 {}
26 25
27 info!("Waiting for vbus...");
28 while !power.usbregstatus.read().vbusdetect().is_vbus_present() {}
29 info!("vbus OK");
30
31 // Create the driver, from the HAL. 26 // Create the driver, from the HAL.
32 let irq = interrupt::take!(USBD); 27 let irq = interrupt::take!(USBD);
33 let driver = Driver::new(p.USBD, irq); 28 let power_irq = interrupt::take!(POWER_CLOCK);
29 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
34 30
35 // Create embassy-usb Config 31 // Create embassy-usb Config
36 let mut config = Config::new(0xc0de, 0xcafe); 32 let mut config = Config::new(0xc0de, 0xcafe);
@@ -101,7 +97,9 @@ impl From<EndpointError> for Disconnected {
101 } 97 }
102} 98}
103 99
104async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { 100async fn echo<'d, T: Instance + 'd, P: UsbSupply + 'd>(
101 class: &mut CdcAcmClass<'d, Driver<'d, T, P>>,
102) -> Result<(), Disconnected> {
105 let mut buf = [0; 64]; 103 let mut buf = [0; 64];
106 loop { 104 loop {
107 let n = class.read_packet(&mut buf).await?; 105 let n = class.read_packet(&mut buf).await?;
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs
index dc503e67c..3806da5a0 100644
--- a/examples/nrf/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf/src/bin/usb_serial_multitask.rs
@@ -8,14 +8,14 @@ use core::mem;
8use defmt::{info, panic, unwrap}; 8use defmt::{info, panic, unwrap};
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::util::Forever; 10use embassy::util::Forever;
11use embassy_nrf::usb::Driver; 11use embassy_nrf::usb::{Driver, PowerUsb};
12use embassy_nrf::{interrupt, pac, peripherals, Peripherals}; 12use embassy_nrf::{interrupt, pac, peripherals, Peripherals};
13use embassy_usb::driver::EndpointError; 13use embassy_usb::driver::EndpointError;
14use embassy_usb::{Builder, Config, UsbDevice}; 14use embassy_usb::{Builder, Config, UsbDevice};
15use embassy_usb_serial::{CdcAcmClass, State}; 15use embassy_usb_serial::{CdcAcmClass, State};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18type MyDriver = Driver<'static, peripherals::USBD>; 18type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
19 19
20#[embassy::task] 20#[embassy::task]
21async fn usb_task(mut device: UsbDevice<'static, MyDriver>) { 21async fn usb_task(mut device: UsbDevice<'static, MyDriver>) {
@@ -35,19 +35,14 @@ async fn echo_task(mut class: CdcAcmClass<'static, MyDriver>) {
35#[embassy::main] 35#[embassy::main]
36async fn main(spawner: Spawner, p: Peripherals) { 36async fn main(spawner: Spawner, p: Peripherals) {
37 let clock: pac::CLOCK = unsafe { mem::transmute(()) }; 37 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
38 let power: pac::POWER = unsafe { mem::transmute(()) };
39 38
40 info!("Enabling ext hfosc..."); 39 info!("Enabling ext hfosc...");
41 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); 40 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
42 while clock.events_hfclkstarted.read().bits() != 1 {} 41 while clock.events_hfclkstarted.read().bits() != 1 {}
43
44 info!("Waiting for vbus...");
45 while !power.usbregstatus.read().vbusdetect().is_vbus_present() {}
46 info!("vbus OK");
47
48 // Create the driver, from the HAL. 42 // Create the driver, from the HAL.
49 let irq = interrupt::take!(USBD); 43 let irq = interrupt::take!(USBD);
50 let driver = Driver::new(p.USBD, irq); 44 let power_irq = interrupt::take!(POWER_CLOCK);
45 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
51 46
52 // Create embassy-usb Config 47 // Create embassy-usb Config
53 let mut config = Config::new(0xc0de, 0xcafe); 48 let mut config = Config::new(0xc0de, 0xcafe);