Update non-IRQ USB example.

This commit is contained in:
Jonathan Pallant (42 Technology) 2021-09-21 10:54:13 +01:00
parent 35f001f61d
commit ba6c409f21
2 changed files with 81 additions and 35 deletions

View file

@ -1,30 +1,64 @@
//! Creates a USB Serial device on a Pico board. //! # Pico USB Serial Example
//! //!
//! This will create a USB Serial device echoing anything it receives converting to caps the ASCII //! Creates a USB Serial device on a Pico board, with the USB driver running in
//! alphabetical caracters. //! the main thread.
//!
//! This will create a USB Serial device echoing anything it receives. Incoming
//! ASCII characters are converted to upercase, so you can tell it is working
//! and not just local-echo!
//!
//! See the `Cargo.toml` file for Copyright and licence details.
#![no_std] #![no_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; use cortex_m_rt::entry;
// Ensure we halt the program on panic (if we don't mention this crate it won't
// be linked)
use panic_halt as _; use panic_halt as _;
use pico::{
hal::{clocks::init_clocks_and_plls, pac, timer::Timer, usb::UsbBus, watchdog::Watchdog}, // A shorter alias for the Peripheral Access Crate, which provides low-level
XOSC_CRYSTAL_FREQ, // register access
}; use pico::hal::pac;
// A shorter alias for the Hardware Abstraction Layer, which provides
// higher-level drivers.
use pico::hal;
// USB Device support
use usb_device::{class_prelude::*, prelude::*}; use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support
use usbd_serial::SerialPort; use usbd_serial::SerialPort;
/// The linker will place this boot block at the start of our program image. We
/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
/// Entry point to our bare-metal application.
///
/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables are initialised.
///
/// The function configures the RP2040 peripherals, then echoes any characters
/// received over USB Serial.
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); let mut pac = pac::Peripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let clocks = init_clocks_and_plls( // Set up the watchdog driver - needed by the clock setup code
XOSC_CRYSTAL_FREQ, let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
// Configure the clocks
//
// Our default is 12 MHz crystal input, 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,
pac.CLOCKS, pac.CLOCKS,
pac.PLL_SYS, pac.PLL_SYS,
@ -35,15 +69,19 @@ fn main() -> ! {
.ok() .ok()
.unwrap(); .unwrap();
let timer = Timer::new(pac.TIMER); // Set up the USB driver
let usb_bus = UsbBusAllocator::new(UsbBus::new( let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new(
pac.USBCTRL_REGS, pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM, pac.USBCTRL_DPRAM,
clocks.usb_clock, clocks.usb_clock,
true, true,
&mut pac.RESETS, &mut pac.RESETS,
)); ));
// Set up the USB Communications Class Device driver
let mut serial = SerialPort::new(&usb_bus); let mut serial = SerialPort::new(&usb_bus);
// Create a USB device with a fake VID and PID
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company") .manufacturer("Fake company")
.product("Serial port") .product("Serial port")
@ -51,36 +89,41 @@ fn main() -> ! {
.device_class(2) // from: https://www.usb.org/defined-class-codes .device_class(2) // from: https://www.usb.org/defined-class-codes
.build(); .build();
let timer = hal::timer::Timer::new(pac.TIMER);
let mut said_hello = false; let mut said_hello = false;
loop { loop {
// A welcome message at the beginning
if !said_hello && timer.get_counter() >= 2_000_000 { if !said_hello && timer.get_counter() >= 2_000_000 {
said_hello = true; said_hello = true;
let _ = serial.write(b"HelloWorld!\r\n"); let _ = serial.write(b"Hello, World!\r\n");
}
if !usb_dev.poll(&mut [&mut serial]) {
continue;
} }
// Check for new data
if usb_dev.poll(&mut [&mut serial]) {
let mut buf = [0u8; 64]; let mut buf = [0u8; 64];
let _ = serial.read(&mut buf).map(|count| { match serial.read(&mut buf) {
if count == 0 { Err(_e) => {
return; // Do nothing
} }
Ok(0) => {
// Echo back in upper case // Do nothing
buf.iter_mut().take(count).for_each(|c| {
if let 0x61..=0x7a = *c {
*c &= !0x20;
} }
Ok(count) => {
// Convert to upper case
buf.iter_mut().take(count).for_each(|b| {
b.make_ascii_uppercase();
}); });
// Send back to the host
let mut wr_ptr = &buf[..count]; let mut wr_ptr = &buf[..count];
while !wr_ptr.is_empty() { while !wr_ptr.is_empty() {
let _ = serial.write(wr_ptr).map(|len| { let _ = serial.write(wr_ptr).map(|len| {
wr_ptr = &wr_ptr[len..]; wr_ptr = &wr_ptr[len..];
}); });
} }
}); }
}
}
} }
} }
// End of file

View file

@ -91,6 +91,7 @@ fn main() -> ! {
.ok() .ok()
.unwrap(); .unwrap();
// Set up the USB driver
let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new( let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new(
pac.USBCTRL_REGS, pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM, pac.USBCTRL_DPRAM,
@ -103,11 +104,13 @@ fn main() -> ! {
USB_BUS = Some(usb_bus); USB_BUS = Some(usb_bus);
} }
// Set up the USB Communications Class Device driver
let serial = SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() }); let serial = SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() });
unsafe { unsafe {
USB_SERIAL = Some(serial); USB_SERIAL = Some(serial);
} }
// Create a USB device with a fake VID and PID
let usb_dev = UsbDeviceBuilder::new( let usb_dev = UsbDeviceBuilder::new(
// Note (safety): This is safe as interrupts haven't been started yet // Note (safety): This is safe as interrupts haven't been started yet
unsafe { USB_BUS.as_ref().unwrap() }, unsafe { USB_BUS.as_ref().unwrap() },