#![no_main]
#![no_std]
use cortex_m;
use cortex_m_rt::entry;
use critical_section::{CriticalSection, with};
use defmt::println;
use defmt_rtt as _;
use hal::{
clocks::{self, Clk48Src, Clocks, CrsSyncSrc, enable_crs},
gpio::{Pin, PinMode, Port},
pac,
prelude::*,
usb::{Peripheral, UsbBus, UsbBusType},
};
use panic_probe as _;
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;
make_globals!(
(USB_DEV, UsbDevice<'static, UsbBusType>),
(USB_SERIAL, SerialPort<'static, UsbBusType>),
);
fn init() {
let mut cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let mut clock_cfg = Clocks {
hsi48_on: true,
clk48_src: Clk48Src::Hsi48,
..Default::default()
};
clock_cfg.setup().unwrap();
clock_cfg::enable_crs(CrsSyncSrc::Usb);
let usb = Peripheral { usb: dp.USB };
let usb_bus = UsbBus::new(usb);
let usb_serial = SerialPort::new(usb_bus);
let usb_serial = SerialPort::new_with_store(
unsafe { USB_BUS.as_ref().unwrap() },
unsafe { &mut USB_TX_STORE[..] },
unsafe { &mut USB_RX_STORE[..] },
);
let usb_dev = UsbDeviceBuilder::new(
unsafe { USB_BUS.as_ref().unwrap() },
UsbVidPid(0x16c0, 0x27dd),
)
.strings(&[StringDescriptors::default()
.manufacturer("A Company")
.product("Serial port")
.serial_number("SN")])
.unwrap()
.device_class(usbd_serial::USB_CLASS_CDC)
.build();
init_globals!((USB_DEVICE, usb_device), (USB_SERIAL, usb_serial));
setup_nvic!([(USB_FS, 1),], cp);
}
pub fn handle_rx(
usb_serial: &mut UsbSerial<'static>,
usb_dev: &mut UsbDevice<'static, UsbBusType>,
rx_buf: &[u8],
cs: CriticalSection,
) {
println!("Received a message over USB: {:?}", rx_buf);
if rx_buf[0] == 10 {
let mut tx_buf = [0; 10];
let msg_len = 10;
let mut offset = 0;
while offset < msg_len {
match usb_serial.write(&tx_buf[offset..msg_len]) {
Ok(0) | Err(UsbError::WouldBlock) => {
usb_dev.poll(&mut [usb_serial]);
}
Ok(written) => offset += written,
Err(e) => {
defmt::warn!("USB write error: {:?}", e);
break;
}
}
}
while usb_serial.flush().err() == Some(UsbError::WouldBlock) {
usb_dev.poll(&mut [usb_serial]);
}
}
}
#[entry]
fn main() -> ! {
init();
loop {
asm::nop();
}
}
#[interrupt]
fn USB_LP() {
with(|cs| {
access_globals!([(USB_DEV, dev), (USB_SERIAL, serial),], cs);
if !dev.poll(&mut [serial]) {
return;
}
let mut rx_buf = [0; 10];
if let Ok(count) = serial.read(&mut rx_buf) {
println!("Bytes read: {}", count);
handle_rx(serial, dev, &rx_buf, cs);
}
});
}
#[defmt::panic_handler]
fn panic() -> ! {
cortex_m::asm::udf()
}