#![no_std] #![no_main] extern crate panic_semihosting; use core::cell::RefCell; use core::ops::DerefMut; use cortex_m::asm::wfi; use cortex_m::interrupt::{free as interrupt_free, Mutex}; use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use embedded_hal::digital::v2::OutputPin; use stm32f1xx_hal::stm32::{self, interrupt, Interrupt}; use stm32f1xx_hal::usb::{Peripheral, UsbBusType}; use stm32f1xx_hal::{delay::Delay, prelude::*}; use usb_device::bus::UsbBusAllocator; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[cfg(not(feature = "atomic"))] use bbqueue::{consts::*, BBBuffer, ConstBBBuffer, Producer}; static RX_QUEUE: BBBuffer = BBBuffer(ConstBBBuffer::new()); static RX_PROD: Mutex>>> = Mutex::new(RefCell::new(None)); static mut USB_BUS: Option> = None; static USB_DEVICE: Mutex>>> = Mutex::new(RefCell::new(None)); static SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { let cp = cortex_m::Peripherals::take().unwrap(); let dp = stm32::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()); let mut delay = Delay::new(cp.SYST, clocks); // 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().ok(); // Turn off let mut gpioa = dp.GPIOA.split(&mut rcc.apb2); let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); usb_dp.set_low().unwrap(); delay.delay_ms(10u16); let usb_bus; unsafe { let usb_peripherial = Peripheral { usb: dp.USB, pin_dm: gpioa.pa11, pin_dp: usb_dp.into_floating_input(&mut gpioa.crh), }; USB_BUS = Some(UsbBusType::new(usb_peripherial)); usb_bus = USB_BUS.as_ref().unwrap(); } let (rx_prod, mut rx_cons) = RX_QUEUE.try_split().unwrap(); interrupt_free(|cs| { SERIAL.borrow(cs).replace(Some(SerialPort::new(usb_bus))); USB_DEVICE.borrow(cs).replace(Some( UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Ar3itrary Embedded") .product("usart-demo") .serial_number("2342") .device_class(USB_CLASS_CDC) .build(), )); RX_PROD.borrow(cs).replace(Some(rx_prod)); }); unsafe { NVIC::unmask(Interrupt::USB_HP_CAN_TX); NVIC::unmask(Interrupt::USB_LP_CAN_RX0); } loop { wfi(); if let Ok(rgr) = rx_cons.read() { for c in rgr.iter() { let resp = match *c { 97u8 => { led.set_high().unwrap(); "LED turned off\n\r" } 98u8 => { led.set_low().unwrap(); "LED turned on\n\r" } _ => "", }; interrupt_free(|cs| { if let Some(serial) = SERIAL.borrow(cs).borrow_mut().deref_mut() { serial.write(resp.as_bytes()).unwrap(); } }); } let len = rgr.len(); rgr.release(len); } } } #[interrupt] fn USB_HP_CAN_TX() { usb_interrupt(); } #[interrupt] fn USB_LP_CAN_RX0() { usb_interrupt(); } fn usb_interrupt() { interrupt_free(|cs| { if let Some(usb_dev) = USB_DEVICE.borrow(cs).borrow_mut().deref_mut() { if let Some(serial) = SERIAL.borrow(cs).borrow_mut().deref_mut() { if !usb_dev.poll(&mut [serial]) { return; } if let Some(rx_prod) = RX_PROD.borrow(cs).borrow_mut().deref_mut() { if let Ok(mut wgr) = rx_prod.grant_exact(64) { match serial.read(&mut wgr) { Ok(count) if count > 0 => { wgr.commit(count); } _ => wgr.commit(0), } } } } } }); }