-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add additional example for the Adafruit KB2040.
- Loading branch information
1 parent
49d3079
commit a5dc9d7
Showing
3 changed files
with
162 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
boards/adafruit-kb2040/examples/adafruit_kb2040_usb_serial.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
//! # Pico USB Serial Example | ||
//! | ||
//! Creates a USB Serial device on a Pico board, with the USB driver running in | ||
//! 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 license details. | ||
#![no_std] | ||
#![no_main] | ||
|
||
use adafruit_kb2040 as bsp; | ||
|
||
// The macro for our start-up function | ||
use bsp::entry; | ||
|
||
// Ensure we halt the program on panic (if we don't mention this crate it won't | ||
// be linked) | ||
use panic_halt as _; | ||
|
||
// A shorter alias for the Peripheral Access Crate, which provides low-level | ||
// register access | ||
use bsp::hal::pac; | ||
|
||
// A shorter alias for the Hardware Abstraction Layer, which provides | ||
// higher-level drivers. | ||
use bsp::hal; | ||
|
||
// USB Device support | ||
use usb_device::{class_prelude::*, prelude::*}; | ||
|
||
// USB Communications Class Device support | ||
use usbd_serial::SerialPort; | ||
|
||
// Used to demonstrate writing formatted strings | ||
use core::fmt::Write; | ||
use heapless::String; | ||
|
||
/// 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] | ||
fn main() -> ! { | ||
// Grab our singleton objects | ||
let mut pac = pac::Peripherals::take().unwrap(); | ||
|
||
// Set up the watchdog driver - needed by the clock setup code | ||
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); | ||
|
||
// Configure the clocks | ||
// | ||
// The default is to generate a 125 MHz system clock | ||
let clocks = hal::clocks::init_clocks_and_plls( | ||
bsp::XOSC_CRYSTAL_FREQ, | ||
pac.XOSC, | ||
pac.CLOCKS, | ||
pac.PLL_SYS, | ||
pac.PLL_USB, | ||
&mut pac.RESETS, | ||
&mut watchdog, | ||
) | ||
.ok() | ||
.unwrap(); | ||
|
||
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); | ||
|
||
#[cfg(feature = "rp2040-e5")] | ||
{ | ||
let sio = hal::Sio::new(pac.SIO); | ||
let _pins = bsp::Pins::new( | ||
pac.IO_BANK0, | ||
pac.PADS_BANK0, | ||
sio.gpio_bank0, | ||
&mut pac.RESETS, | ||
); | ||
} | ||
|
||
// Set up the USB driver | ||
let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new( | ||
pac.USBCTRL_REGS, | ||
pac.USBCTRL_DPRAM, | ||
clocks.usb_clock, | ||
true, | ||
&mut pac.RESETS, | ||
)); | ||
|
||
// Set up the USB Communications Class Device driver | ||
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)) | ||
.manufacturer("Fake company") | ||
.product("Serial port") | ||
.serial_number("TEST") | ||
.device_class(2) // from: https://www.usb.org/defined-class-codes | ||
.build(); | ||
|
||
let mut said_hello = false; | ||
loop { | ||
// A welcome message at the beginning | ||
if !said_hello && timer.get_counter().ticks() >= 2_000_000 { | ||
said_hello = true; | ||
let _ = serial.write(b"Hello, World!\r\n"); | ||
|
||
let time = timer.get_counter().ticks(); | ||
let mut text: String<64> = String::new(); | ||
writeln!(&mut text, "Current timer ticks: {}", time).unwrap(); | ||
|
||
// This only works reliably because the number of bytes written to | ||
// the serial port is smaller than the buffers available to the USB | ||
// peripheral. In general, the return value should be handled, so that | ||
// bytes not transferred yet don't get lost. | ||
let _ = serial.write(text.as_bytes()); | ||
} | ||
|
||
// Check for new data | ||
if usb_dev.poll(&mut [&mut serial]) { | ||
let mut buf = [0u8; 64]; | ||
match serial.read(&mut buf) { | ||
Err(_e) => { | ||
// Do nothing | ||
} | ||
Ok(0) => { | ||
// Do nothing | ||
} | ||
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]; | ||
while !wr_ptr.is_empty() { | ||
match serial.write(wr_ptr) { | ||
Ok(len) => wr_ptr = &wr_ptr[len..], | ||
// On error, just drop unwritten data. | ||
// One possible error is Err(WouldBlock), meaning the USB | ||
// write buffer is full. | ||
Err(_) => break, | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// End of file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#![no_std] | ||
|
||
pub use rp2040_hal as hal; | ||
|
||
#[cfg(feature = "rt")] | ||
extern crate cortex_m_rt; | ||
#[cfg(feature = "rt")] | ||
|