aboutsummaryrefslogtreecommitdiff
path: root/examples/nrf52840/src/bin/usb_serial_multitask.rs
diff options
context:
space:
mode:
authorDominik Boehi <[email protected]>2023-01-09 22:29:58 +0100
committerDominik Boehi <[email protected]>2023-01-09 22:30:02 +0100
commit0a27b6cedb52453123190671f294bbd34918e09a (patch)
tree3888e0b352388ace235517ec97c4d3a88fd7fcfa /examples/nrf52840/src/bin/usb_serial_multitask.rs
parent401185b1d95a2519ee94e5d5654cc9325fe85eec (diff)
Rename examples/nrf to examples/nrf52840
Diffstat (limited to 'examples/nrf52840/src/bin/usb_serial_multitask.rs')
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
new file mode 100644
index 000000000..93efc2fe6
--- /dev/null
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -0,0 +1,118 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::mem;
6
7use defmt::{info, panic, unwrap};
8use embassy_executor::Spawner;
9use embassy_nrf::usb::{Driver, PowerUsb};
10use embassy_nrf::{interrupt, pac, peripherals};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config, UsbDevice};
14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _};
16
17type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
18
19#[embassy_executor::task]
20async fn usb_task(mut device: UsbDevice<'static, MyDriver>) {
21 device.run().await;
22}
23
24#[embassy_executor::task]
25async fn echo_task(mut class: CdcAcmClass<'static, MyDriver>) {
26 loop {
27 class.wait_connection().await;
28 info!("Connected");
29 let _ = echo(&mut class).await;
30 info!("Disconnected");
31 }
32}
33
34#[embassy_executor::main]
35async fn main(spawner: Spawner) {
36 let p = embassy_nrf::init(Default::default());
37 let clock: pac::CLOCK = unsafe { mem::transmute(()) };
38
39 info!("Enabling ext hfosc...");
40 clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
41 while clock.events_hfclkstarted.read().bits() != 1 {}
42 // Create the driver, from the HAL.
43 let irq = interrupt::take!(USBD);
44 let power_irq = interrupt::take!(POWER_CLOCK);
45 let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
46
47 // Create embassy-usb Config
48 let mut config = Config::new(0xc0de, 0xcafe);
49 config.manufacturer = Some("Embassy");
50 config.product = Some("USB-serial example");
51 config.serial_number = Some("12345678");
52 config.max_power = 100;
53 config.max_packet_size_0 = 64;
54
55 // Required for windows compatiblity.
56 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
57 config.device_class = 0xEF;
58 config.device_sub_class = 0x02;
59 config.device_protocol = 0x01;
60 config.composite_with_iads = true;
61
62 struct Resources {
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
78 // Create embassy-usb DeviceBuilder using the driver and config.
79 let mut builder = Builder::new(
80 driver,
81 config,
82 &mut res.device_descriptor,
83 &mut res.config_descriptor,
84 &mut res.bos_descriptor,
85 &mut res.control_buf,
86 None,
87 );
88
89 // Create classes on the builder.
90 let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64);
91
92 // Build the builder.
93 let usb = builder.build();
94
95 unwrap!(spawner.spawn(usb_task(usb)));
96 unwrap!(spawner.spawn(echo_task(class)));
97}
98
99struct Disconnected {}
100
101impl From<EndpointError> for Disconnected {
102 fn from(val: EndpointError) -> Self {
103 match val {
104 EndpointError::BufferOverflow => panic!("Buffer overflow"),
105 EndpointError::Disabled => Disconnected {},
106 }
107 }
108}
109
110async fn echo(class: &mut CdcAcmClass<'static, MyDriver>) -> Result<(), Disconnected> {
111 let mut buf = [0; 64];
112 loop {
113 let n = class.read_packet(&mut buf).await?;
114 let data = &buf[..n];
115 info!("data: {:x}", data);
116 class.write_packet(data).await?;
117 }
118}