Fix stuff

This commit is contained in:
2021-05-06 23:57:55 +02:00
parent ecd2d92b52
commit 684dbbd882
8 changed files with 415 additions and 163 deletions

200
Cargo.lock generated
View File

@ -1,10 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aligned"
version = "0.3.2"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94"
checksum = "c19796bd8d477f1a9d4ac2465b464a8b1359474f06a96bb3cda650b4fca309bf"
dependencies = [
"as-slice",
]
@ -21,27 +23,33 @@ dependencies = [
[[package]]
name = "as-slice"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37dfb65bc03b2bc85ee827004f14a6817e04160e3b1a28931986a666a9290e70"
checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
dependencies = [
"generic-array 0.12.3",
"generic-array 0.13.2",
"generic-array 0.12.4",
"generic-array 0.13.3",
"generic-array 0.14.4",
"stable_deref_trait",
]
[[package]]
name = "atsamd-hal"
version = "0.12.0"
source = "git+https://github.com/atsamd-rs/atsamd#8e507a7b76c441d87d302b107c6b06485e9b6478"
source = "git+https://github.com/atsamd-rs/atsamd#db1f9b70d351ff73546b012e23b48115e6dfed6c"
dependencies = [
"atsamd21g",
"bitfield",
"bitflags",
"cortex-m",
"embedded-hal",
"nb",
"modular-bitfield",
"nb 0.1.3",
"num-traits",
"paste",
"rand_core",
"seq-macro",
"typenum",
"usb-device",
"vcell",
"void",
@ -50,7 +58,7 @@ dependencies = [
[[package]]
name = "atsamd21g"
version = "0.9.0"
source = "git+https://github.com/atsamd-rs/atsamd#8e507a7b76c441d87d302b107c6b06485e9b6478"
source = "git+https://github.com/atsamd-rs/atsamd#db1f9b70d351ff73546b012e23b48115e6dfed6c"
dependencies = [
"bare-metal",
"cortex-m",
@ -58,6 +66,12 @@ dependencies = [
"vcell",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bare-metal"
version = "0.2.5"
@ -74,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "470e1522d257e4c76245980d27d5d279442cb18955cc6341249b904074033f4a"
dependencies = [
"embedded-hal",
"nb",
"nb 0.1.3",
]
[[package]]
@ -84,10 +98,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]]
name = "bytemuck"
version = "1.5.0"
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bytemuck"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
[[package]]
name = "byteorder"
@ -97,20 +117,21 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cortex-m"
version = "0.6.2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763"
checksum = "88cdafeafba636c00c467ded7f1587210725a1adfab0c24028a7844b87738263"
dependencies = [
"aligned",
"bare-metal",
"bitfield",
"volatile-register",
]
[[package]]
name = "cortex-m-rt"
version = "0.6.12"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00d518da72bba39496024b62607c1d8e37bcece44b2536664f1132a73a499a28"
checksum = "980c9d0233a909f355ed297ef122f257942de5e0a2cb1c39f60684b65bcb90fb"
dependencies = [
"cortex-m-rt-macros",
"r0",
@ -143,7 +164,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b"
dependencies = [
"nb",
"nb 0.1.3",
"void",
]
@ -155,26 +176,36 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "generic-array"
version = "0.12.3"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.13.2"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"typenum",
"version_check 0.9.3",
]
[[package]]
name = "itsybitsy_m0"
version = "0.10.0"
source = "git+https://github.com/atsamd-rs/atsamd#8e507a7b76c441d87d302b107c6b06485e9b6478"
source = "git+https://github.com/atsamd-rs/atsamd#db1f9b70d351ff73546b012e23b48115e6dfed6c"
dependencies = [
"apa102-spi",
"atsamd-hal",
@ -182,7 +213,7 @@ dependencies = [
"cortex-m",
"cortex-m-rt",
"embedded-hal",
"nb",
"nb 0.1.3",
"smart-leds",
"usb-device",
"usbd-hid",
@ -191,15 +222,45 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.3.3"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "modular-bitfield"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
dependencies = [
"modular-bitfield-impl",
"static_assertions",
]
[[package]]
name = "modular-bitfield-impl"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "nb"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [
"nb 1.0.0",
]
[[package]]
name = "nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
[[package]]
name = "neowatch"
@ -211,7 +272,7 @@ dependencies = [
"embedded-graphics",
"embedded-hal",
"itsybitsy_m0",
"nb",
"nb 0.1.3",
"ssd1351",
"usb-device",
"usbd-serial",
@ -229,34 +290,43 @@ dependencies = [
[[package]]
name = "nom"
version = "5.1.1"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"memchr",
"version_check 0.9.1",
"version_check 0.9.3",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "paste"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1"
checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
[[package]]
name = "proc-macro2"
version = "1.0.10"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.3"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
@ -275,9 +345,9 @@ checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
[[package]]
name = "rgb"
version = "0.8.25"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287f3c3f8236abb92d8b7e36797f19159df4b58f0a658cc3fb6dd3004b1f3bd3"
checksum = "8fddb3b23626145d1776addfc307e1a1851f60ef6ca64f376bcb889697144cf0"
dependencies = [
"bytemuck",
]
@ -307,10 +377,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.122"
name = "seq-macro"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "974ef1bd2ad8a507599b336595454081ff68a9599b4890af7643c0c0ed73a62c"
checksum = "d5b3bd665f328d73d7079123bfbd14a6edd74187667b5c6f340adfc65ea9d25a"
[[package]]
name = "serde"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
[[package]]
name = "smart-leds"
@ -350,15 +426,21 @@ dependencies = [
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.17"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
dependencies = [
"proc-macro2",
"quote",
@ -371,7 +453,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d12b7f8b271567d6d072c49dee16b22271aabfc473e2066e3353e5af0f5230"
dependencies = [
"nom 5.1.1",
"nom 5.1.2",
]
[[package]]
@ -385,21 +467,21 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.12.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]]
name = "unicode-xid"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "usb-device"
version = "0.2.7"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "849eed9b4dc61a1f17ba1d7a5078ceb095b9410caa38a506eb281ed5eff12fbd"
checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245"
[[package]]
name = "usbd-hid"
@ -443,15 +525,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe"
dependencies = [
"embedded-hal",
"nb",
"nb 0.1.3",
"usb-device",
]
[[package]]
name = "vcell"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "version_check"
@ -461,9 +543,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]]
name = "version_check"
version = "0.9.1"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"

View File

@ -1,20 +1,20 @@
[tasks.build]
description = "Build the executable"
command = "cargo"
args = ["build"]
args = ["build", "--release"]
[tasks.objcopy]
decsription = "Transform the binary for upload"
description = "Transform the binary for upload"
command = "arm-none-eabi-objcopy"
args = [
"-O", "binary",
"target/thumbv6m-none-eabi/debug/neowatch",
"target/thumbv6m-none-eabi/debug/neowatch.bin",
"target/thumbv6m-none-eabi/release/neowatch",
"target/thumbv6m-none-eabi/release/neowatch.bin",
]
dependencies = ["build"]
[tasks.wait_for_tty]
decsription = "Wait for serial port to be available for upload"
description = "Wait for serial port to be available for upload"
script = [
'''
#!/bin/sh
@ -32,7 +32,7 @@ done
disabled = true
[tasks.upload]
decsription = "Upload the program to the device"
description = "Upload the program to the device"
command = "bossac"
args = [
"--info",
@ -42,7 +42,7 @@ args = [
"--erase",
"--write",
"--verify",
"target/thumbv6m-none-eabi/debug/neowatch.bin",
"target/thumbv6m-none-eabi/release/neowatch.bin",
"--reset",
]
dependencies = ["objcopy", "wait_for_tty"]

View File

@ -10,15 +10,16 @@ mod rn4020;
mod bl_demo;
mod display_demo;
mod ring_buffer;
mod usb_shell;
mod util;
mod wait_delay;
use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::entry;
use hal::pac::{interrupt, CorePeripherals, Peripherals};
use hal::prelude::*;
use usb_shell::{init, poll_usb};
use usb_shell::{init, usb_read};
use wait_delay::WaitDelay;
#[entry]
@ -38,37 +39,31 @@ fn main() -> ! {
let mut blip = || {
red_led.set_low().ok();
delay.delay_ms(200u8);
delay.delay_ms(100u16);
red_led.toggle();
delay.delay_ms(200u8);
delay.delay_ms(100u16);
};
blip();
init(
let mut usb = init(
&mut core.NVIC,
peripherals.USB,
&mut clocks,
&mut peripherals.PM,
pins.usb_dm,
pins.usb_dp,
&mut pins.port,
&mut blip,
);
blip();
blip();
blip();
blip();
// Flash the LED in a spin loop to demonstrate that USB is
// entirely interrupt driven.
loop {
blip();
usb.poll();
//usb.println(b"woop");
}
}
#[interrupt]
fn USB() {
poll_usb();
usb_read();
}

48
src/ring_buffer.rs Normal file
View File

@ -0,0 +1,48 @@
pub struct RingBuffer<T, const N: usize> {
buffer: [T; N],
start: usize,
end: usize,
}
impl<const N: usize> RingBuffer<u8, N> {
pub const fn new() -> Self {
RingBuffer {
buffer: [0; N],
start: 0,
end: 0,
}
}
}
impl<T, const N: usize> RingBuffer<T, N>
where
T: Copy,
{
pub fn push_back(&mut self, element: T) -> Result<(), T> {
let next_end = (self.end + 1) % N;
if next_end == self.start {
return Err(element);
}
self.buffer[self.end] = element;
self.end = next_end;
Ok(())
}
pub fn pop_front(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
let element = self.buffer[self.start];
self.start = (self.start + 1) % N;
Some(element)
}
pub fn is_empty(&self) -> bool {
self.start == self.end
}
}

View File

@ -1,5 +1,8 @@
mod cmds;
use crate::ring_buffer::RingBuffer;
use crate::util::cell::RacyCell;
use core::mem::MaybeUninit;
use core::str::from_utf8;
use core::sync::atomic::AtomicBool;
use core::sync::atomic::Ordering;
@ -7,7 +10,7 @@ use cortex_m::peripheral::NVIC;
use hal::clock::GenericClockController;
use hal::gpio::{
v2::{PA24, PA25},
Pin, Port,
Pin,
};
use hal::pac::{interrupt, PM, USB};
use hal::usb::UsbBus;
@ -15,50 +18,53 @@ use usb_device::bus::UsbBusAllocator;
use usb_device::prelude::*;
use usbd_serial::{SerialPort, USB_CLASS_CDC};
struct ShellState {
pub struct UsbShell {
line_buf: [u8; 255],
buf_size: usize,
buf_len: usize,
}
static USB_READY: AtomicBool = AtomicBool::new(false);
static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
static mut USB_BUS: Option<UsbDevice<UsbBus>> = None;
static mut USB_SERIAL: Option<SerialPort<UsbBus>> = None;
static mut SHELL_STATE: Option<ShellState> = None;
static INPUT_BUFFER: RacyCell<RingBuffer<u8, 255>> = RacyCell::new(RingBuffer::new());
const PROMPT: &[u8] = b"[neowatch]# ";
pub fn init<F: FnMut()>(
nvic: &mut NVIC,
//bus_allocator: UsbBusAllocator<UsbBus>,
usb: USB,
clocks: &mut GenericClockController,
pm: &mut PM,
usb_dm: Pin<PA24, hal::gpio::v2::Input<hal::gpio::v2::Floating>>,
usb_dp: Pin<PA25, hal::gpio::v2::Input<hal::gpio::v2::Floating>>,
port: &mut Port,
f: &mut F,
) {
) -> UsbShell {
if USB_READY.load(Ordering::SeqCst) {
panic!("usb::init called more than once");
}
let bus_allocator = unsafe {
USB_ALLOCATOR = Some(hal::usb_allocator(usb, clocks, pm, usb_dm, usb_dp, port));
USB_ALLOCATOR.as_ref().unwrap()
static USB_ALLOCATOR: RacyCell<MaybeUninit<UsbBusAllocator<UsbBus>>> =
RacyCell::new(MaybeUninit::uninit());
let allocator = &mut *USB_ALLOCATOR.get();
*allocator = MaybeUninit::new(hal::usb_allocator(usb, clocks, pm, usb_dm, usb_dp));
&mut *allocator.as_mut_ptr()
};
f();
unsafe {
USB_SERIAL = Some(SerialPort::new(&bus_allocator));
USB_SERIAL = Some(SerialPort::new(bus_allocator));
USB_BUS = Some(
UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x16c0, 0x27dd))
UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.build(),
);
SHELL_STATE = Some(ShellState {
line_buf: [0; 255],
buf_size: 0,
});
}
f();
@ -72,76 +78,184 @@ pub fn init<F: FnMut()>(
NVIC::unmask(interrupt::USB);
f();
}
UsbShell {
buf_len: 0,
line_buf: [0; 255],
}
}
pub fn poll_usb() {
impl UsbShell {
/// Output a line to the USB serial
pub fn println(&mut self, s: &[u8]) {
internal::usb_mutex(|_bus, serial| {
internal::println(serial, self, s).ok();
});
}
/// Call periodically to consume input
pub fn poll(&mut self) {
internal::usb_mutex(|_bus, serial| {
let input_buffer = unsafe { &mut *INPUT_BUFFER.get() };
while let Some(input) = input_buffer.pop_front() {
internal::handle_input(self, serial, input).ok();
}
});
}
}
/// Call from USB interrupt handler
pub fn usb_read() {
// make sure that the usb state was initialized properly
if !USB_READY.load(Ordering::SeqCst) {
return;
}
unsafe { USB_BUS.as_mut() }
.zip(unsafe { USB_SERIAL.as_mut() })
.zip(unsafe { SHELL_STATE.as_mut() })
.map(|((bus, serial), state)| {
bus.poll(&mut [serial]);
let mut buf = [0u8; 64];
fn f(bus: &mut UsbDevice<UsbBus>, serial: &mut SerialPort<UsbBus>) {
bus.poll(&mut [serial]);
let mut buf = [0u8; 64];
if let Ok(count) = serial.read(&mut buf) {
for &c in buf.iter().take(count) {
match c {
b'\t' => {}
127 | 08 /* del or backspace */ => {
if state.buf_size > 0 {
// FIXME: This is not utf-8 compatible. It should decrease
// buf_size by the size of the last unicode scalar.
state.buf_size -= 1;
// erase previous character
serial.write(&[08, b' ', 08]).unwrap();
}
}
b'\n' | b'\r' => {
if state.buf_size > 0 {
serial.write(b"\r\n").unwrap();
match from_utf8(&state.line_buf[..state.buf_size]) {
Ok(s) => {
let mut args = s.split(" ");
let arg0 = args.next().unwrap_or("");
if let Ok(count) = serial.read(&mut buf) {
for &c in buf.iter().take(count) {
let input_buffer = unsafe { &mut *INPUT_BUFFER.get() };
if let Err(_) = input_buffer.push_back(c) {
//internal::println(serial, b"error: input buffer full").ok();
}
}
match arg0 {
"help" => cmds::help::exec(args, serial),
"echo" => cmds::echo::exec(args, serial),
_ => {
serial.write(b"Unknown command: ").unwrap();
serial.write(arg0.as_bytes()).unwrap();
}
}
}
Err(_) => {
serial.write(b"ERROR: not valid utf-8").unwrap();
}
crate::wait_delay::wakeup();
};
}
// SAFETY: mutual exclusion is guaranteed if this function is called from an interrupt handler
unsafe { internal::usb_with_state(f) };
}
mod internal {
use super::*;
const NEWLINE: &[u8] = b"\r\n";
/// Acquire USB state and execute function
///
/// User must guarantee mutual exclusion
pub(super) unsafe fn usb_with_state<F>(f: F)
where
F: FnOnce(&mut UsbDevice<UsbBus>, &mut SerialPort<UsbBus>),
{
USB_BUS
.as_mut()
.zip(USB_SERIAL.as_mut())
.map(|(bus, serial)| f(bus, serial));
}
/// Acquire USB state and execute function with interrupts disabled
pub(super) fn usb_mutex<F>(f: F)
where
F: FnOnce(&mut UsbDevice<UsbBus>, &mut SerialPort<UsbBus>),
{
// enter critical section
NVIC::mask(interrupt::USB);
// SAFETY: interrupts are disabled. should be good.
unsafe { usb_with_state(f) };
// exit critical section
unsafe { NVIC::unmask(interrupt::USB) };
}
pub(super) fn clear_char(serial: &mut SerialPort<UsbBus>) -> Result<(), UsbError> {
serial.write(&[08, b' ', 08])?;
Ok(())
}
pub(super) fn clear_prompt(
serial: &mut SerialPort<UsbBus>,
state: &UsbShell,
) -> Result<(), UsbError> {
for _ in 0..(state.buf_len + PROMPT.len()) {
// FIXME: This is not utf-8 compatible. It should decrease
// buf_len by the size of the last unicode scalar.
clear_char(serial)?;
}
Ok(())
}
pub(super) fn show_prompt(
serial: &mut SerialPort<UsbBus>,
state: &UsbShell,
) -> Result<(), UsbError> {
serial.write(PROMPT)?;
serial.write(&state.line_buf[..state.buf_len])?;
Ok(())
}
pub(super) fn println(
serial: &mut SerialPort<UsbBus>,
state: &UsbShell,
s: &[u8],
) -> Result<(), UsbError> {
clear_prompt(serial, state)?;
serial.write(s)?;
serial.write(NEWLINE)?;
show_prompt(serial, state)?;
Ok(())
}
pub(super) fn handle_input(
state: &mut UsbShell,
serial: &mut SerialPort<UsbBus>,
input: u8,
) -> Result<(), UsbError> {
match input {
b'\t' => {}
127 | 08 /* del or backspace */ => {
if state.buf_len > 0 {
// FIXME: This is not utf-8 compatible. It should decrease
// buf_len by the size of the last unicode scalar.
state.buf_len -= 1;
clear_char(serial)?;
}
}
b'\n' | b'\r' => {
if state.buf_len > 0 {
serial.write(NEWLINE)?;
match from_utf8(&state.line_buf[..state.buf_len]) {
Ok(s) => {
let mut args = s.split(" ");
let arg0 = args.next().unwrap_or("");
match arg0 {
"help" => cmds::help::exec(args, serial),
"echo" => cmds::echo::exec(args, serial),
_ => {
serial.write(b"Unknown command: ")?;
serial.write(arg0.as_bytes())?;
}
}
serial.write(b"\r\n").unwrap();
serial.write(PROMPT).unwrap();
state.buf_size = 0;
}
_ => {
if state.buf_size >= state.line_buf.len() {
state.buf_size = 0;
serial
.write(b"\r\nERROR: line buffer size exceeded\r\n")
.unwrap();
break;
}
state.line_buf[state.buf_size] = c;
state.buf_size += 1;
serial.write(&[c]).unwrap();
Err(_) => {
serial.write(b"ERROR: not valid utf-8")?;
}
}
}
state.buf_len = 0;
serial.write(NEWLINE)?;
show_prompt(serial, state)?;
}
_ => {
if state.buf_len >= state.line_buf.len() {
state.buf_len = 0;
serial
.write(b"\r\nERROR: line buffer size exceeded\r\n")?;
}
crate::wait_delay::wakeup();
};
});
state.line_buf[state.buf_len] = input;
state.buf_len += 1;
serial.write(&[input])?;
}
}
Ok(())
}
}

15
src/util/cell.rs Normal file
View File

@ -0,0 +1,15 @@
use core::cell::UnsafeCell;
pub struct RacyCell<T>(pub UnsafeCell<T>);
unsafe impl<T> Sync for RacyCell<T> {}
impl<T> RacyCell<T> {
pub const fn new(inner: T) -> Self {
RacyCell(UnsafeCell::new(inner))
}
pub fn get(&self) -> *mut T {
self.0.get()
}
}

1
src/util/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod cell;

View File

@ -1,18 +1,16 @@
//! Delay module for waking the system up
use core::sync::atomic::{AtomicBool, Ordering};
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
use itsybitsy_m0::clock::GenericClockController;
use itsybitsy_m0::time::Hertz;
static mut SLEEPING: bool = false;
static SLEEPING: AtomicBool = AtomicBool::new(false);
pub fn wakeup() {
unsafe {
SLEEPING = false;
}
SLEEPING.store(false, Ordering::SeqCst);
}
/// System timer (SysTick) as a delay provider
@ -33,6 +31,7 @@ impl WaitDelay {
}
/// Releases the system timer (SysTick) resource
#[allow(dead_code)]
pub fn free(self) -> SYST {
self.syst
}
@ -63,11 +62,9 @@ impl DelayUs<u32> for WaitDelay {
let mut total_rvr = us * (self.sysclock.0 / 1_000_000);
//unsafe {
// SLEEPING = true;
//}
SLEEPING.store(true, Ordering::SeqCst);
while total_rvr != 0 {
while total_rvr != 0 && SLEEPING.load(Ordering::SeqCst) {
let current_rvr = if total_rvr <= MAX_RVR {
total_rvr
} else {
@ -81,7 +78,7 @@ impl DelayUs<u32> for WaitDelay {
// Update the tracking variable while we are waiting...
total_rvr -= current_rvr;
while !self.syst.has_wrapped() {}
while !self.syst.has_wrapped() && SLEEPING.load(Ordering::SeqCst) {}
self.syst.disable_counter();
}