//! CDC-ACM serial port example using polling in a busy loop. #![no_std] #![no_main] extern crate panic_semihosting; extern crate stm32wb_hal as hal; use cortex_m_rt::{entry, exception, ExceptionFrame}; use hal::flash::FlashExt; use hal::pac; use hal::prelude::*; use hal::rcc::{ApbDivider, Config, HDivider, HseDivider, PllConfig, PllSrc, SysClkSrc, UsbClkSrc}; use hal::usb::{Peripheral, UsbBus}; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[entry] fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let rcc = dp.RCC.constrain(); // Fastest clock configuration. // * 32 MHz HSE with PLL // * 64 MHz CPU1, 32 MHz CPU2 // * 64 MHz for APB1, APB2 // * USB clock source from PLLQ (32 / 2 * 3 = 48) let clock_config = Config::new(SysClkSrc::Pll(PllSrc::Hse(HseDivider::NotDivided))) .cpu1_hdiv(HDivider::NotDivided) .cpu2_hdiv(HDivider::Div2) .apb1_div(ApbDivider::NotDivided) .apb2_div(ApbDivider::NotDivided) .pll_cfg(PllConfig { m: 2, n: 12, r: 3, q: Some(4), p: Some(3), }) .usb_src(UsbClkSrc::PllQ); let mut rcc = rcc.apply_clock_config(clock_config, &mut dp.FLASH.constrain().acr); // Enable USB power supply hal::pwr::set_usb(true); let mut gpioa = dp.GPIOA.split(&mut rcc); let usb = Peripheral { usb: dp.USB, pin_dm: gpioa.pa11.into_af10(&mut gpioa.moder, &mut gpioa.afrh), pin_dp: gpioa.pa12.into_af10(&mut gpioa.moder, &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 => { // 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; } _ => {} } } } _ => {} } } } #[exception] #[allow(non_snake_case)] fn HardFault(ef: &ExceptionFrame) -> ! { panic!("HardFault at {:#?}", ef); } #[exception] #[allow(non_snake_case)] fn DefaultHandler(irqn: i16) { panic!("Unhandled exception (IRQn = {})", irqn); }