aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32g0/src/bin
diff options
context:
space:
mode:
authorDerek Hageman <[email protected]>2024-01-04 07:53:31 -0700
committerDerek Hageman <[email protected]>2024-01-05 07:57:35 -0700
commitd34910dbc88d4d4b7cf907b17dd6ed4fd7e2f39c (patch)
tree2407e6f6771b0954a0727fc7349827ea491e6315 /examples/stm32g0/src/bin
parent801a36c7b4e476388e55c842dec09d7ef2607a5a (diff)
stm32: Add G0 USB example
Add a USB CDC ACM example using STM32G0 USB and CRS.
Diffstat (limited to 'examples/stm32g0/src/bin')
-rw-r--r--examples/stm32g0/src/bin/usb_serial.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/examples/stm32g0/src/bin/usb_serial.rs b/examples/stm32g0/src/bin/usb_serial.rs
new file mode 100644
index 000000000..f5aaa5624
--- /dev/null
+++ b/examples/stm32g0/src/bin/usb_serial.rs
@@ -0,0 +1,99 @@
1#![no_std]
2#![no_main]
3
4use defmt::{panic, *};
5use embassy_executor::Spawner;
6use embassy_futures::join::join;
7use embassy_stm32::rcc::{Hsi48Config, UsbSrc};
8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _};
14
15bind_interrupts!(struct Irqs {
16 USB_UCPD1_2 => usb::InterruptHandler<peripherals::USB>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 let mut config = Config::default();
22 config.rcc.usb_src = Some(UsbSrc::Hsi48(Hsi48Config {
23 sync_from_usb: true,
24 ..Default::default()
25 }));
26 let p = embassy_stm32::init(config);
27
28 info!("Hello World!");
29
30 // Create the driver, from the HAL.
31 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
32
33 // Create embassy-usb Config
34 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
35 //config.max_packet_size_0 = 64;
36
37 // Create embassy-usb DeviceBuilder using the driver and config.
38 // It needs some buffers for building the descriptors.
39 let mut device_descriptor = [0; 256];
40 let mut config_descriptor = [0; 256];
41 let mut bos_descriptor = [0; 256];
42 let mut control_buf = [0; 7];
43
44 let mut state = State::new();
45
46 let mut builder = Builder::new(
47 driver,
48 config,
49 &mut device_descriptor,
50 &mut config_descriptor,
51 &mut bos_descriptor,
52 &mut [], // no msos descriptors
53 &mut control_buf,
54 );
55
56 // Create classes on the builder.
57 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
58
59 // Build the builder.
60 let mut usb = builder.build();
61
62 // Run the USB device.
63 let usb_fut = usb.run();
64
65 // Do stuff with the class!
66 let echo_fut = async {
67 loop {
68 class.wait_connection().await;
69 info!("Connected");
70 let _ = echo(&mut class).await;
71 info!("Disconnected");
72 }
73 };
74
75 // Run everything concurrently.
76 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
77 join(usb_fut, echo_fut).await;
78}
79
80struct Disconnected {}
81
82impl From<EndpointError> for Disconnected {
83 fn from(val: EndpointError) -> Self {
84 match val {
85 EndpointError::BufferOverflow => panic!("Buffer overflow"),
86 EndpointError::Disabled => Disconnected {},
87 }
88 }
89}
90
91async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
92 let mut buf = [0; 64];
93 loop {
94 let n = class.read_packet(&mut buf).await?;
95 let data = &buf[..n];
96 info!("data: {:x}", data);
97 class.write_packet(data).await?;
98 }
99}