aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32l5/src/bin/usb_serial.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-05-30 00:36:30 +0200
committerDario Nieuwenhuis <[email protected]>2022-06-07 03:29:00 +0200
commit3e4bead32161604c08e2dcae1acea695db851f34 (patch)
tree41b0334cad6fef5a54e28789ec0320f21000b2ac /examples/stm32l5/src/bin/usb_serial.rs
parent0aa73f58e2f71f4578ff23f79f3b1a2c9d6d9098 (diff)
stm32: add USB driver.
Diffstat (limited to 'examples/stm32l5/src/bin/usb_serial.rs')
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs112
1 files changed, 112 insertions, 0 deletions
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
new file mode 100644
index 000000000..987f1b692
--- /dev/null
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -0,0 +1,112 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::panic;
6use defmt::*;
7use defmt_rtt as _; // global logger
8use embassy::executor::Spawner;
9use embassy_stm32::interrupt;
10use embassy_stm32::rcc::*;
11use embassy_stm32::time::Hertz;
12use embassy_stm32::usb::{Driver, Instance};
13use embassy_stm32::{Config, Peripherals};
14use embassy_usb::driver::EndpointError;
15use embassy_usb::Builder;
16use embassy_usb_serial::{CdcAcmClass, State};
17use futures::future::join;
18use panic_probe as _;
19
20fn config() -> Config {
21 let mut config = Config::default();
22 config.rcc.mux = ClockSrc::HSE(Hertz(16_000_000));
23
24 config.rcc.mux = ClockSrc::PLL(
25 PLLSource::HSI16,
26 PLLClkDiv::Div2,
27 PLLSrcDiv::Div1,
28 PLLMul::Mul10,
29 None,
30 );
31 config.rcc.hsi48 = true;
32
33 config
34}
35
36#[embassy::main(config = "config()")]
37async fn main(_spawner: Spawner, p: Peripherals) {
38 info!("Hello World!");
39
40 // Create the driver, from the HAL.
41 let irq = interrupt::take!(USB_FS);
42 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
43
44 // Create embassy-usb Config
45 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
46 //config.max_packet_size_0 = 64;
47
48 // Create embassy-usb DeviceBuilder using the driver and config.
49 // It needs some buffers for building the descriptors.
50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 7];
54
55 let mut state = State::new();
56
57 let mut builder = Builder::new(
58 driver,
59 config,
60 &mut device_descriptor,
61 &mut config_descriptor,
62 &mut bos_descriptor,
63 &mut control_buf,
64 None,
65 );
66
67 // Create classes on the builder.
68 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
69
70 // Build the builder.
71 let mut usb = builder.build();
72
73 // Run the USB device.
74 let usb_fut = usb.run();
75
76 // Do stuff with the class!
77 let echo_fut = async {
78 loop {
79 class.wait_connection().await;
80 info!("Connected");
81 let _ = echo(&mut class).await;
82 info!("Disconnected");
83 }
84 };
85
86 // Run everything concurrently.
87 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
88 join(usb_fut, echo_fut).await;
89}
90
91struct Disconnected {}
92
93impl From<EndpointError> for Disconnected {
94 fn from(val: EndpointError) -> Self {
95 match val {
96 EndpointError::BufferOverflow => panic!("Buffer overflow"),
97 EndpointError::Disabled => Disconnected {},
98 }
99 }
100}
101
102async fn echo<'d, T: Instance + 'd>(
103 class: &mut CdcAcmClass<'d, Driver<'d, T>>,
104) -> Result<(), Disconnected> {
105 let mut buf = [0; 64];
106 loop {
107 let n = class.read_packet(&mut buf).await?;
108 let data = &buf[..n];
109 info!("data: {:x}", data);
110 class.write_packet(data).await?;
111 }
112}