//! CDC-ACM serial port example using polling in a busy loop. //! Target board: NUCLEO-L432KC #![no_std] #![no_main] extern crate panic_semihosting; use cortex_m_rt::entry; use stm32l4xx_hal::usb::{Peripheral, UsbBus}; use stm32l4xx_hal::{prelude::*, stm32}; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; fn enable_crs() { let rcc = unsafe { &(*stm32::RCC::ptr()) }; rcc.apb1enr1.modify(|_, w| w.crsen().set_bit()); let crs = unsafe { &(*stm32::CRS::ptr()) }; // Initialize clock recovery // Set autotrim enabled. crs.cr.modify(|_, w| w.autotrimen().set_bit()); // Enable CR crs.cr.modify(|_, w| w.cen().set_bit()); } /// Enables VddUSB power supply fn enable_usb_pwr() { // Enable PWR peripheral let rcc = unsafe { &(*stm32::RCC::ptr()) }; rcc.apb1enr1.modify(|_, w| w.pwren().set_bit()); // Enable VddUSB let pwr = unsafe { &*stm32::PWR::ptr() }; pwr.cr2.modify(|_, w| w.usv().set_bit()); } #[entry] fn main() -> ! { let dp = stm32::Peripherals::take().unwrap(); let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1); let _clocks = rcc .cfgr .hsi48(true) .sysclk(80.MHz()) .freeze(&mut flash.acr, &mut pwr); enable_crs(); // disable Vddusb power isolation enable_usb_pwr(); // Configure the on-board LED (LD3, green) let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2); let mut led = gpiob .pb3 .into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper); led.set_low(); // Turn off let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2); let usb = Peripheral { usb: dp.USB, pin_dm: gpioa .pa11 .into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), pin_dp: gpioa .pa12 .into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), }; 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 } }