From 83a0e618f34bf6221ff1b195521b80387aa42496 Mon Sep 17 00:00:00 2001 From: Vadim Kaushan Date: Wed, 13 Nov 2019 14:30:41 +0300 Subject: [PATCH] Add USB example --- Cargo.toml | 6 +++ examples/usb_serial.rs | 90 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 examples/usb_serial.rs diff --git a/Cargo.toml b/Cargo.toml index 5c2f5b8..3aae6a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,8 @@ stm32-usbd = { version = "0.5.0", features = ["ram_access_2x16"], optional = tru [dev-dependencies] panic-halt = "0.2" +usb-device = "0.2.3" +usbd-serial = "0.1.0" [features] device-selected = [] @@ -81,3 +83,7 @@ required-features = ["stm32f042", "rt"] [[example]] name = "dac" required-features = ["stm32f072"] + +[[example]] +name = "usb_serial" +required-features = ["rt", "stm32f042", "stm32-usbd"] diff --git a/examples/usb_serial.rs b/examples/usb_serial.rs new file mode 100644 index 0000000..4fbeb69 --- /dev/null +++ b/examples/usb_serial.rs @@ -0,0 +1,90 @@ +//! CDC-ACM serial port example using polling in a busy loop. +//! Target board: NUCLEO-F042K6 +#![no_std] +#![no_main] + +extern crate panic_halt; + +use cortex_m_rt::entry; +use stm32f0xx_hal::usb::{Peripheral, UsbBus}; +use stm32f0xx_hal::{prelude::*, stm32}; +use usb_device::prelude::*; +use usbd_serial::{SerialPort, USB_CLASS_CDC}; + +#[entry] +fn main() -> ! { + let mut dp = stm32::Peripherals::take().unwrap(); + + /* Uncomment the following lines if you have a chip in TSSOP20 (STM32F042F) + or UFQFPN28 (STM32F042G) package + This code enables clock for SYSCFG and remaps USB pins to PA9 and PA10. + */ + //dp.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit()); + //dp.SYSCFG.cfgr1.modify(|_, w| w.pa11_pa12_rmp().remapped()); + + let mut rcc = dp + .RCC + .configure() + .hsi48() + .enable_crs(dp.CRS) + .sysclk(48.mhz()) + .pclk(24.mhz()) + .freeze(&mut dp.FLASH); + + // Configure the on-board LED (LD3, green) + let gpiob = dp.GPIOB.split(&mut rcc); + let mut led = cortex_m::interrupt::free(|cs| gpiob.pb3.into_push_pull_output(cs)); + led.set_low(); // Turn off + + let gpioa = dp.GPIOA.split(&mut rcc); + + let usb = Peripheral { + usb: dp.USB, + pin_dm: gpioa.pa11, + pin_dp: gpioa.pa12, + }; + let usb_bus = UsbBus::new(usb); + + let mut serial = SerialPort::new(&usb_bus); + + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST") + .device_class(USB_CLASS_CDC) + .build(); + + loop { + if !usb_dev.poll(&mut [&mut serial]) { + continue; + } + + let mut buf = [0u8; 64]; + + match serial.read(&mut buf) { + Ok(count) if count > 0 => { + led.set_high(); // Turn on + + // Echo back in upper case + for c in buf[0..count].iter_mut() { + if 0x61 <= *c && *c <= 0x7a { + *c &= !0x20; + } + } + + let mut write_offset = 0; + while write_offset < count { + match serial.write(&buf[write_offset..count]) { + Ok(len) if len > 0 => { + write_offset += len; + } + _ => {} + } + } + } + _ => {} + } + + led.set_low(); // Turn off + } +}