//! CDC-ACM serial port example using polling in a busy loop. //! Target board: Blue Pill #![no_std] #![no_main] extern crate panic_semihosting; use cortex_m::asm::delay; use cortex_m_rt::entry; use embedded_hal::digital::OutputPin; use stm32f1xx_hal::usb::{Peripheral, UsbBus}; use stm32f1xx_hal::{prelude::*, stm32}; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[entry] fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); let clocks = rcc .cfgr .use_hse(8.mhz()) .sysclk(48.mhz()) .pclk1(24.mhz()) .freeze(&mut flash.acr); assert!(clocks.usbclk_valid()); // Configure the on-board LED (PC13, green) let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); led.set_high(); // Turn off let mut gpioa = dp.GPIOA.split(&mut rcc.apb2); // BluePill board has a pull-up resistor on the D+ line. // Pull the D+ pin down to send a RESET condition to the USB bus. // This forced reset is needed only for development, without it host // will not reset your device when you upload new firmware. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); usb_dp.set_low(); delay(clocks.sysclk().0 / 100); let usb = Peripheral { usb: dp.USB, pin_dm: gpioa.pa11, pin_dp: usb_dp.into_floating_input(&mut gpioa.crh), }; 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_low(); // 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_high(); // Turn off } }