aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32f1/src/bin
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/stm32f1/src/bin
parent0aa73f58e2f71f4578ff23f79f3b1a2c9d6d9098 (diff)
stm32: add USB driver.
Diffstat (limited to 'examples/stm32f1/src/bin')
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
new file mode 100644
index 000000000..fe4aa4cc9
--- /dev/null
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -0,0 +1,117 @@
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::time::Duration;
10use embassy::time::Timer;
11use embassy_stm32::gpio::Level;
12use embassy_stm32::gpio::Output;
13use embassy_stm32::gpio::Speed;
14use embassy_stm32::interrupt;
15use embassy_stm32::time::Hertz;
16use embassy_stm32::usb::{Driver, Instance};
17use embassy_stm32::{Config, Peripherals};
18use embassy_usb::driver::EndpointError;
19use embassy_usb::Builder;
20use embassy_usb_serial::{CdcAcmClass, State};
21use futures::future::join;
22use panic_probe as _;
23
24fn config() -> Config {
25 let mut config = Config::default();
26 config.rcc.hse = Some(Hertz(8_000_000));
27 config.rcc.sys_ck = Some(Hertz(48_000_000));
28 config.rcc.pclk1 = Some(Hertz(24_000_000));
29 config
30}
31
32#[embassy::main(config = "config()")]
33async fn main(_spawner: Spawner, mut p: Peripherals) {
34 info!("Hello World!");
35
36 {
37 // BluePill board has a pull-up resistor on the D+ line.
38 // Pull the D+ pin down to send a RESET condition to the USB bus.
39 // This forced reset is needed only for development, without it host
40 // will not reset your device when you upload new firmware.
41 let _dp = Output::new(&mut p.PA12, Level::Low, Speed::Low);
42 Timer::after(Duration::from_millis(10)).await;
43 }
44
45 // Create the driver, from the HAL.
46 let irq = interrupt::take!(USB_LP_CAN1_RX0);
47 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
48
49 // Create embassy-usb Config
50 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
51 //config.max_packet_size_0 = 64;
52
53 // Create embassy-usb DeviceBuilder using the driver and config.
54 // It needs some buffers for building the descriptors.
55 let mut device_descriptor = [0; 256];
56 let mut config_descriptor = [0; 256];
57 let mut bos_descriptor = [0; 256];
58 let mut control_buf = [0; 7];
59
60 let mut state = State::new();
61
62 let mut builder = Builder::new(
63 driver,
64 config,
65 &mut device_descriptor,
66 &mut config_descriptor,
67 &mut bos_descriptor,
68 &mut control_buf,
69 None,
70 );
71
72 // Create classes on the builder.
73 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
74
75 // Build the builder.
76 let mut usb = builder.build();
77
78 // Run the USB device.
79 let usb_fut = usb.run();
80
81 // Do stuff with the class!
82 let echo_fut = async {
83 loop {
84 class.wait_connection().await;
85 info!("Connected");
86 let _ = echo(&mut class).await;
87 info!("Disconnected");
88 }
89 };
90
91 // Run everything concurrently.
92 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
93 join(usb_fut, echo_fut).await;
94}
95
96struct Disconnected {}
97
98impl From<EndpointError> for Disconnected {
99 fn from(val: EndpointError) -> Self {
100 match val {
101 EndpointError::BufferOverflow => panic!("Buffer overflow"),
102 EndpointError::Disabled => Disconnected {},
103 }
104 }
105}
106
107async fn echo<'d, T: Instance + 'd>(
108 class: &mut CdcAcmClass<'d, Driver<'d, T>>,
109) -> Result<(), Disconnected> {
110 let mut buf = [0; 64];
111 loop {
112 let n = class.read_packet(&mut buf).await?;
113 let data = &buf[..n];
114 info!("data: {:x}", data);
115 class.write_packet(data).await?;
116 }
117}