#![no_std]
#![no_main]
#[rtic::app(device = board, peripherals = false)]
mod app {
use hal::usbd::{BusAdapter, EndpointMemory, EndpointState, Speed};
use imxrt_hal as hal;
use usb_device::{
bus::UsbBusAllocator,
device::{UsbDevice, UsbDeviceBuilder, UsbDeviceState, UsbVidPid},
};
use usbd_serial::SerialPort;
const SPEED: Speed = Speed::High;
const VID_PID: UsbVidPid = UsbVidPid(0x5824, 0x27dd);
const PRODUCT: &str = "imxrt-hal-example";
const LPUART_POLL_INTERVAL_MS: u32 = board::PIT_FREQUENCY / 1_000 * 100;
const FRONTEND: board::logging::Frontend = board::logging::Frontend::Log;
static EP_MEMORY: EndpointMemory<2048> = EndpointMemory::new();
static EP_STATE: EndpointState = EndpointState::max_endpoints();
type Bus = BusAdapter;
#[local]
struct Local {
class: SerialPort<'static, Bus>,
device: UsbDevice<'static, Bus>,
led: board::Led,
poller: board::logging::Poller,
timer: hal::pit::Pit<0>,
}
#[shared]
struct Shared {}
#[init(local = [bus: Option<UsbBusAllocator<Bus>> = None])]
fn init(ctx: init::Context) -> (Shared, Local) {
let (
board::Common {
pit: (mut timer, _, _, _),
usb1,
usbnc1,
usbphy1,
mut dma,
..
},
board::Specifics { led, console, .. },
) = board::new();
timer.set_load_timer_value(LPUART_POLL_INTERVAL_MS);
timer.set_interrupt_enable(true);
timer.enable();
let dma_a = dma[board::BOARD_DMA_A_INDEX].take().unwrap();
let poller = board::logging::lpuart(FRONTEND, console, dma_a);
let usbd = hal::usbd::Instances {
usb: usb1,
usbnc: usbnc1,
usbphy: usbphy1,
};
let bus = BusAdapter::with_speed(usbd, &EP_MEMORY, &EP_STATE, SPEED);
bus.set_interrupts(true);
let bus = ctx.local.bus.insert(UsbBusAllocator::new(bus));
let class = SerialPort::new(bus);
let device = UsbDeviceBuilder::new(bus, VID_PID)
.product(PRODUCT)
.device_class(usbd_serial::USB_CLASS_CDC)
.max_packet_size_0(64)
.build();
(
Shared {},
Local {
class,
device,
led,
poller,
timer,
},
)
}
#[task(binds = BOARD_PIT, local = [poller, timer], priority = 1)]
fn pit_interrupt(ctx: pit_interrupt::Context) {
while ctx.local.timer.is_elapsed() {
ctx.local.timer.clear_elapsed();
}
ctx.local.poller.poll();
}
#[task(binds = BOARD_USB1, local = [class, device, led, configured: bool = false], priority = 2)]
fn usb1(ctx: usb1::Context) {
let usb1::LocalResources {
class,
device,
configured,
led,
..
} = ctx.local;
if device.poll(&mut [class]) {
if device.state() == UsbDeviceState::Configured {
if !*configured {
device.bus().configure();
}
*configured = true;
let mut buffer = [0; 64];
match class.read(&mut buffer) {
Ok(count) => {
led.toggle();
class.write(&buffer[..count]).ok();
log::info!(
"Received '{}' from the host",
core::str::from_utf8(&buffer[..count]).unwrap_or("???")
);
}
Err(usb_device::UsbError::WouldBlock) => {}
Err(err) => log::error!("{err:?}"),
}
} else {
*configured = false;
}
}
}
}