mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-01-11 21:11:31 +11:00
Update non-IRQ USB example.
This commit is contained in:
parent
35f001f61d
commit
ba6c409f21
|
@ -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
|
||||||
|
|
|
@ -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() },
|
||||||
|
|
Loading…
Reference in a new issue