Skip to content

Instantly share code, notes, and snippets.

@sajattack
Created August 7, 2020 01:12
Show Gist options
  • Select an option

  • Save sajattack/8deca7c0a96b4390250f6d31fb18508f to your computer and use it in GitHub Desktop.

Select an option

Save sajattack/8deca7c0a96b4390250f6d31fb18508f to your computer and use it in GitHub Desktop.
#![no_std]
#![no_main]
extern crate metro_m4 as hal;
extern crate cortex_m;
extern crate panic_halt;
extern crate usb_device;
extern crate usbd_serial;
use hal::clock::GenericClockController;
use hal::entry;
use hal::pac::{interrupt, CorePeripherals, Peripherals};
use hal::prelude::*;
use hal::usb::UsbBus;
use usb_device::bus::UsbBusAllocator;
use usb_device::prelude::*;
use usbd_serial::{SerialPort, USB_CLASS_CDC};
use cortex_m::asm::delay as cycle_delay;
use cortex_m::peripheral::NVIC;
#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let mut core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.MCLK,
&mut peripherals.OSC32KCTRL,
&mut peripherals.OSCCTRL,
&mut peripherals.NVMCTRL,
);
let mut pins = hal::Pins::new(peripherals.PORT);
let mut red_led = pins.d13.into_open_drain_output(&mut pins.port);
let bus_allocator = unsafe {
USB_ALLOCATOR = Some(hal::usb_allocator(
pins.usb_dm,
pins.usb_dp,
peripherals.USB,
&mut clocks,
&mut peripherals.MCLK,
&mut pins.port,
));
USB_ALLOCATOR.as_ref().unwrap()
};
unsafe {
USB_SERIAL = Some(SerialPort::new(&bus_allocator));
USB_BUS = Some(
UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x2222, 0x3333))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.build(),
);
}
unsafe {
core.NVIC.set_priority(interrupt::USB_TRCPT0, 1);
NVIC::unmask(interrupt::USB_TRCPT0);
core.NVIC.set_priority(interrupt::USB_TRCPT1, 1);
NVIC::unmask(interrupt::USB_TRCPT1);
core.NVIC.set_priority(interrupt::USB_SOF_HSOF, 1);
NVIC::unmask(interrupt::USB_SOF_HSOF);
core.NVIC.set_priority(interrupt::USB_OTHER, 1);
NVIC::unmask(interrupt::USB_OTHER);
}
let tc0 = peripherals.TC0;
// Flash the LED in a spin loop to demonstrate that USB is
// entirely interrupt driven.
loop {
cycle_delay(5 * 1024 * 1024);
red_led.toggle();
// Turn off interrupts so we don't fight with the interrupt
cortex_m::interrupt::free(|_| unsafe {
USB_BUS.as_mut().map(|_| {
USB_SERIAL.as_mut().map(|serial| {
let _ = serial.write("log: ".as_bytes());
tc0.count16().ctrla.write(|w| w.dmaos().set_bit());
if tc0.count16().ctrla.read().dmaos().bit_is_set() {
let _ = serial.write("bit is set\r\n".as_bytes());
} else {
let _ = serial.write("bit is not set\r\n".as_bytes());
}
});
})
});
}
}
static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
static mut USB_BUS: Option<UsbDevice<UsbBus>> = None;
static mut USB_SERIAL: Option<SerialPort<UsbBus>> = None;
fn poll_usb() {
unsafe {
USB_BUS.as_mut().map(|usb_dev| {
USB_SERIAL.as_mut().map(|serial| {
usb_dev.poll(&mut [serial]);
// Make the other side happy
let mut buf = [0u8; 16];
let _ = serial.read(&mut buf);
});
});
};
}
#[interrupt]
fn USB_TRCPT0() {
poll_usb();
}
#[interrupt]
fn USB_TRCPT1() {
poll_usb();
}
#[interrupt]
fn USB_SOF_HSOF() {
poll_usb();
}
#[interrupt]
fn USB_OTHER() {
poll_usb();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment