aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-09-05 12:06:22 +0000
committerGitHub <[email protected]>2025-09-05 12:06:22 +0000
commit70aaa82e490a8c5637de7e38cb636f04c1d187f7 (patch)
tree04b95747f4133e22cb74824500a12b5610c93537
parentf2de2ca16b4fdb623a73de4d349c68c7292a8f11 (diff)
parent160ee7f8054b374ce4c14b6877e6a05f5a5614b7 (diff)
Merge pull request #4623 from paroga/stm32l0_usb_serial
stm32/l0: Add usb serial example
-rw-r--r--examples/stm32l0/Cargo.toml2
-rw-r--r--examples/stm32l0/src/bin/usb_serial.rs95
2 files changed, 97 insertions, 0 deletions
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 90f57a2d8..d42cdac15 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -11,6 +11,8 @@ embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
14 16
15defmt = "1.0.1" 17defmt = "1.0.1"
16defmt-rtt = "1.0.0" 18defmt-rtt = "1.0.0"
diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs
new file mode 100644
index 000000000..fdb1aeb59
--- /dev/null
+++ b/examples/stm32l0/src/bin/usb_serial.rs
@@ -0,0 +1,95 @@
1#![no_std]
2#![no_main]
3
4use defmt::{panic, *};
5use embassy_executor::Spawner;
6use embassy_futures::join::join;
7use embassy_stm32::usb::{self, Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 USB => usb::InterruptHandler<peripherals::USB>;
16});
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 let mut config = embassy_stm32::Config::default();
21 {
22 use embassy_stm32::rcc::*;
23 config.rcc.hsi = true;
24 config.rcc.pll = Some(Pll {
25 source: PllSource::HSI,
26 mul: PllMul::MUL6, // PLLVCO = 16*6 = 96Mhz
27 div: PllDiv::DIV3, // 32Mhz clock (16 * 6 / 3)
28 });
29 config.rcc.sys = Sysclk::PLL1_R;
30 }
31
32 let p = embassy_stm32::init(config);
33
34 info!("Hello World!");
35
36 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
37
38 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
39 config.manufacturer = Some("Embassy");
40 config.product = Some("USB-Serial Example");
41 config.serial_number = Some("123456");
42
43 let mut config_descriptor = [0; 256];
44 let mut bos_descriptor = [0; 256];
45 let mut control_buf = [0; 64];
46
47 let mut state = State::new();
48
49 let mut builder = Builder::new(
50 driver,
51 config,
52 &mut config_descriptor,
53 &mut bos_descriptor,
54 &mut [], // no msos descriptors
55 &mut control_buf,
56 );
57
58 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
59
60 let mut usb = builder.build();
61
62 let usb_fut = usb.run();
63
64 let echo_fut = async {
65 loop {
66 class.wait_connection().await;
67 info!("Connected");
68 let _ = echo(&mut class).await;
69 info!("Disconnected");
70 }
71 };
72
73 join(usb_fut, echo_fut).await;
74}
75
76struct Disconnected {}
77
78impl From<EndpointError> for Disconnected {
79 fn from(val: EndpointError) -> Self {
80 match val {
81 EndpointError::BufferOverflow => panic!("Buffer overflow"),
82 EndpointError::Disabled => Disconnected {},
83 }
84 }
85}
86
87async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
88 let mut buf = [0; 64];
89 loop {
90 let n = class.read_packet(&mut buf).await?;
91 let data = &buf[..n];
92 info!("data: {:x}", data);
93 class.write_packet(data).await?;
94 }
95}