Skip to content

Commit 08a4caa

Browse files
bors[bot]no111u3
andauthored
Merge #553
553: Add rtic-usb-cdc-echo example r=burrbull a=no111u3 Co-authored-by: Boris Vinogradov <[email protected]>
2 parents dd7538f + 723bf81 commit 08a4caa

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
5151
- Added Transactional I2C API [#542]
5252
- Added rtic-usart-shell example [#551]
5353
- Added rtic-usart-shell-ssd1306 example [#551]
54+
- Added rtic-usb-cdc-echo example [#553]
5455

5556

5657
[#481]: https://github.com/stm32-rs/stm32f4xx-hal/pull/481
@@ -73,6 +74,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
7374
[#527]: https://github.com/stm32-rs/stm32f4xx-hal/pull/527
7475
[#551]: https://github.com/stm32-rs/stm32f4xx-hal/pull/551
7576
[#552]: https://github.com/stm32-rs/stm32f4xx-hal/pull/552
77+
[#553]: https://github.com/stm32-rs/stm32f4xx-hal/pull/552
7678

7779
## [v0.13.2] - 2022-05-16
7880

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,10 @@ required-features = ["stm32f411", "rtic"] # stm32f411
474474
name = "rtic-usart-shell-ssd1306"
475475
required-features = ["stm32f411", "rtic"] # stm32f411
476476

477+
[[example]]
478+
name = "rtic-usb-cdc-echo"
479+
required-features = ["stm32f411", "rtic"] # stm32f411
480+
477481
[[example]]
478482
name = "sd"
479483
required-features = ["gpiod", "sdio", "sdio-host"] # stm32f405

examples/rtic-usb-cdc-echo.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use panic_halt as _;
5+
6+
#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [USART1])]
7+
mod app {
8+
use stm32f4xx_hal::{
9+
gpio::{Output, PC13},
10+
otg_fs::{UsbBus, UsbBusType, USB},
11+
pac,
12+
prelude::*,
13+
timer::MonoTimerUs,
14+
};
15+
16+
use usb_device::prelude::*;
17+
use usbd_serial::SerialPort;
18+
19+
#[shared]
20+
struct Shared {
21+
usb_dev: UsbDevice<'static, UsbBusType>,
22+
usb_serial: SerialPort<'static, UsbBusType>,
23+
}
24+
25+
#[local]
26+
struct Local {
27+
led: PC13<Output>,
28+
}
29+
30+
#[monotonic(binds = TIM2, default = true)]
31+
type MicrosecMono = MonoTimerUs<pac::TIM2>;
32+
33+
#[init]
34+
fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
35+
static mut EP_MEMORY: [u32; 1024] = [0; 1024];
36+
static mut USB_BUS: Option<usb_device::bus::UsbBusAllocator<UsbBusType>> = None;
37+
38+
let dp = ctx.device;
39+
40+
let rcc = dp.RCC.constrain();
41+
// Setup system clocks
42+
let hse = 25.MHz();
43+
let sysclk = 84.MHz();
44+
let clocks = rcc
45+
.cfgr
46+
.use_hse(hse)
47+
.sysclk(sysclk)
48+
.require_pll48clk()
49+
.freeze();
50+
51+
let gpioa = dp.GPIOA.split();
52+
let gpioc = dp.GPIOC.split();
53+
let led = gpioc.pc13.into_push_pull_output();
54+
55+
let mono = dp.TIM2.monotonic_us(&clocks);
56+
tick::spawn().ok();
57+
58+
// *** Begin USB setup ***
59+
let usb = USB {
60+
usb_global: dp.OTG_FS_GLOBAL,
61+
usb_device: dp.OTG_FS_DEVICE,
62+
usb_pwrclk: dp.OTG_FS_PWRCLK,
63+
pin_dm: gpioa.pa11.into_alternate(),
64+
pin_dp: gpioa.pa12.into_alternate(),
65+
hclk: clocks.hclk(),
66+
};
67+
unsafe {
68+
USB_BUS.replace(UsbBus::new(usb, &mut EP_MEMORY));
69+
}
70+
71+
let usb_serial = usbd_serial::SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() });
72+
let usb_dev = UsbDeviceBuilder::new(
73+
unsafe { USB_BUS.as_ref().unwrap() },
74+
UsbVidPid(0x16c0, 0x27dd),
75+
)
76+
.manufacturer("rust embedded")
77+
.product("usb echo server")
78+
.serial_number("4242")
79+
.device_class(usbd_serial::USB_CLASS_CDC)
80+
.build();
81+
82+
(
83+
Shared {
84+
usb_dev,
85+
usb_serial,
86+
},
87+
Local { led },
88+
init::Monotonics(mono),
89+
)
90+
}
91+
92+
#[task(local = [led])]
93+
fn tick(ctx: tick::Context) {
94+
tick::spawn_after(1.secs()).ok();
95+
ctx.local.led.toggle();
96+
}
97+
98+
#[task(binds=OTG_FS, shared=[usb_dev, usb_serial])]
99+
fn usb_fs(cx: usb_fs::Context) {
100+
let usb_fs::SharedResources {
101+
mut usb_dev,
102+
mut usb_serial,
103+
} = cx.shared;
104+
105+
(&mut usb_dev, &mut usb_serial).lock(|usb_dev, usb_serial| {
106+
if usb_dev.poll(&mut [usb_serial]) {
107+
let mut buf = [0u8; 64];
108+
109+
match usb_serial.read(&mut buf) {
110+
Ok(count) if count > 0 => {
111+
let mut write_offset = 0;
112+
while write_offset < count {
113+
match usb_serial.write(&mut buf[write_offset..count]) {
114+
Ok(len) if len > 0 => {
115+
write_offset += len;
116+
}
117+
_ => {}
118+
}
119+
}
120+
}
121+
_ => {}
122+
}
123+
}
124+
});
125+
}
126+
}

0 commit comments

Comments
 (0)