remove outdated code; add puzzle source code

This commit is contained in:
Jorge Aparicio 2020-07-09 18:58:02 +02:00
parent ae9d58aa43
commit e093f48807
6 changed files with 117 additions and 421 deletions

View file

@ -1,54 +0,0 @@
[package]
authors = ["Jorge Aparicio <jorge.aparicio@ferrous-systems.com>"]
edition = "2018"
name = "dongle"
version = "0.1.0"
[dependencies]
consts = { path = "../../common/consts" }
cortex-m-rt = "0.6.12"
cortex-m-rtfm = "0.5.1"
embedded-hal = "0.2.3"
hal = { package = "nrf52840-hal", git = "https://github.com/japaric/nrf-hal", branch = "143+144" }
heapless = "0.5.5"
panic-halt = "0.2.0"
usb-device = "0.2.5"
usbd-serial = "0.1.0"
# optimize code in both profiles
[profile.dev]
codegen-units = 1
debug = 1
debug-assertions = true # !
incremental = false
lto = "fat"
opt-level = 'z' # !
overflow-checks = false
[profile.release]
codegen-units = 1
debug = 1
debug-assertions = false
incremental = false
lto = "fat"
opt-level = 3
overflow-checks = false
# faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[patch.crates-io.usb-device]
git = "https://github.com/jonas-schievink/usb-device.git"
branch = "inhibit-setaddr-resp"

View file

@ -16,11 +16,11 @@ use panic_abort as _;
fn main() -> ! {
let mut stx = usbd::serial();
let (mut rtx, mut rrx) = radio::claim(Channel::_20);
let mut output = String::<consts::U64>::new();
let mut output = String::::new();
output.push_str("deviceid=").ok();
write!(output, "{:08x}{:08x}", hal::deviceid1(), hal::deviceid0()).ok();
write!(output, " channel={} TxPower=+8dBm\n", rtx.channel()).ok();
write!(output, " channel={} TxPower=+8dBm app=loopback.hex\n", rtx.channel()).ok();
let task = async {
let mut packet = Packet::new().await;
@ -28,7 +28,8 @@ fn main() -> ! {
loop {
let crcres = rrx.read(&mut packet).await;
let lqi = if packet.len() >= 3 {
let len = packet.len();
let lqi = if len >= 3 {
Some(packet.lqi())
} else {
// packet is too small; LQI is not valid
@ -37,12 +38,11 @@ fn main() -> ! {
let mut busy = false;
if crcres.is_ok() {
// packet.reverse();
packet.reverse();
busy = rtx.write(&packet).await.is_err();
}
output.clear();
let len = packet.len();
write!(
&mut output,
"received {} byte{}",

112
boards/dongle/puzzle.rs Normal file
View file

@ -0,0 +1,112 @@
// f6c27c0a5af464795d1a64c45fa1b3039f44a62a
#![deny(unused_must_use)]
#![no_main]
#![no_std]
use core::fmt::Write as _;
use hal::{radio::{self, Packet, Channel}, usbd, led};
use heapless::{consts, LinearMap, String};
use panic_abort as _;
static FROM: &[u8] = &[
// <redacted>
];
static TO: &[u8] = &[
// <redacted>
];
// store the secret rather than the plaintext -- otherwise `strings $elf` will reveal the answer
static SECRET: &[u8] = b"<redacted>";
#[no_mangle]
fn main() -> ! {
// so we can visually differentiate this one from `loopback.hex`
led::Green.on();
let mut stx = usbd::serial();
let (mut rtx, mut rrx) = radio::claim(Channel::_25);
let mut output = String::<consts::U128>::new();
let mut dict = LinearMap::<_, _, consts::U128>::new();
for (&from, &to) in FROM.iter().zip(TO.iter()) {
dict.insert(from, to).ok();
}
output.push_str("deviceid=").ok();
write!(output, "{:08x}{:08x}", hal::deviceid1(), hal::deviceid0()).ok();
write!(output, " channel={} TxPower=+8dBm app=puzzle.hex\n", rtx.channel()).ok();
let task = async {
let mut packet = Packet::new().await;
stx.write(output.as_bytes());
loop {
let crcres = rrx.read(&mut packet).await;
let len = packet.len();
let lqi = if len >= 3 {
Some(packet.lqi())
} else {
// packet is too small; LQI is not valid
None
};
let mut busy = false;
if crcres.is_ok() {
if packet.is_empty() {
packet.copy_from_slice(SECRET);
} else if packet.len() == 1 {
let p = packet[0];
let c = dict.get(&p).unwrap_or(&p);
packet.copy_from_slice(&[*c]);
} else {
// encrypt
for slot in packet.iter_mut() {
if let Some(c) = dict.get(slot) {
*slot = *c;
}
}
let matches = &packet[..] == SECRET;
packet.copy_from_slice(if matches {
b"correct"
} else {
b"incorrect"
});
}
busy = rtx.write(&packet).await.is_err();
}
output.clear();
write!(
&mut output,
"received {} byte{}",
len,
if len == 1 { "" } else { "s" }
)
.ok();
let (res, crc) = match crcres {
Ok(x) => ("Ok", x),
Err(x) => ("Err", x),
};
write!(&mut output, " (CRC={}({:#06x})", res, crc).ok();
if let Some(lqi) = lqi {
write!(&mut output, ", LQI={}", lqi).ok();
}
output.push_str(")\n").ok();
if busy {
output.push_str("didn't reply -- channel was busy\n").ok();
stx.write(output.as_bytes());
}
stx.write(output.as_bytes());
}
};
executor::run!(task)
}

View file

@ -1,203 +0,0 @@
//! `radio` & `usb` apps merged into a single application
#![no_std]
#![no_main]
use core::fmt::Write as _;
use core::sync::atomic::{AtomicBool, Ordering};
use embedded_hal::digital::v2::{OutputPin as _, StatefulOutputPin as _};
use hal::{
clocks::{Clocks, ExternalOscillator, Internal, LfOscStopped},
gpio::{
p0::{self, P0_06, P0_12},
Level, Output, PushPull,
},
ieee802154::{Packet, Radio},
target::USBD,
usbd::Usbd,
};
use heapless::String;
use panic_halt as _; // panic handler
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
// TODO make channel configurable via a single `const`ant
#[rtfm::app(device = hal::target, peripherals = true)]
const APP: () = {
struct Resources {
blue: P0_12<Output<PushPull>>,
configured: AtomicBool,
green: P0_06<Output<PushPull>>,
radio: Radio<'static>,
serial_port: SerialPort<'static, Usbd<'static>>,
usb_dev: UsbDevice<'static, Usbd<'static>>,
}
#[init]
fn init(cx: init::Context) -> init::LateResources {
static mut EP_BUF: [u8; 1024] = [0; 1024];
static mut CLOCKS: Option<Clocks<ExternalOscillator, Internal, LfOscStopped>> = None;
static mut USB_BUS: Option<UsbBusAllocator<Usbd<'static>>> = None;
let periph = cx.device;
let port = p0::Parts::new(periph.P0);
// P0.6: green LED indicates USB is working
// P0.12: blue LED is toggled on each new packet
let green = port.p0_06.into_push_pull_output(Level::High);
let blue = port.p0_12.into_push_pull_output(Level::High);
let clocks = Clocks::new(periph.CLOCK);
// extend lifetime to `'static`
let clocks = CLOCKS.get_or_insert(clocks.enable_ext_hfosc());
let mut radio = Radio::init(periph.RADIO, clocks);
// set TX power to its maximum value
radio.set_txpower(8);
// these loops should always terminate
// detected USB power? (device is USB powered)
while !periph
.POWER
.usbregstatus
.read()
.vbusdetect()
.is_vbus_present()
{}
// wait until USB 3.3V supply (internal regulator) is stable
while !periph
.POWER
.events_usbpwrrdy
.read()
.events_usbpwrrdy()
.bit_is_clear()
{}
// enable all interrupts
periph.USBD.intenset.write(|w| {
w.endepin0().set_bit();
w.endepin1().set_bit();
w.endepin2().set_bit();
w.endepout0().set_bit();
w.endepout1().set_bit();
w.endepout2().set_bit();
w.ep0datadone().set_bit();
w.ep0setup().set_bit();
w.epdata().set_bit();
w.usbevent().set_bit();
w.usbreset().set_bit();
w.sof().set_bit();
w
});
let usb_bus = USB_BUS.get_or_insert(Usbd::new_alloc(periph.USBD, EP_BUF, clocks));
let serial_port = SerialPort::new(usb_bus);
let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(consts::VID, consts::PID))
.device_class(USB_CLASS_CDC)
.max_packet_size_0(64) // (makes control transfers 8x faster)
.build();
init::LateResources {
blue,
green,
configured: AtomicBool::new(false),
radio,
usb_dev,
serial_port,
}
}
#[idle(resources = [blue, &configured, radio, serial_port])]
fn idle(cx: idle::Context) -> ! {
let blue = cx.resources.blue;
let configured = cx.resources.configured;
let mut serial_port = cx.resources.serial_port;
let radio = cx.resources.radio;
// TODO run Radio in parallel to the USBD task
let mut packet = Packet::new();
let mut buf = String::<heapless::consts::U64>::new();
loop {
// let res = radio.recv(&mut packet);
// let lqi = packet.lqi();
// let len = packet.len();
// if res.is_ok() {
// if blue.is_set_low() == Ok(true) {
// blue.set_high().ok();
// } else {
// blue.set_low().ok();
// }
// // loopback the packet
// radio.send(&packet);
// }
let is_configured = configured.load(Ordering::Relaxed);
if is_configured {
blue.set_low().ok();
// buf.clear();
// // TODO switch to a single `uwriteln!`
// if res.is_ok() {
// buf.push_str("CRC OK").ok()
// } else {
// buf.push_str("BAD CRC").ok()
// };
// buf.push_str(" - LQI: ").ok();
// write!(buf, "{}", lqi).ok();
// buf.push_str(" - payload: ").ok();
// write!(buf, "{}", len).ok();
// buf.push_str(" bytes\n").ok();
// serial_port.lock(|port| port.write(buf.as_bytes()).ok());
}
}
}
#[task(binds = USBD, resources = [&configured, green, usb_dev, serial_port])]
fn usbd(cx: usbd::Context) {
let configured = cx.resources.configured;
let green = cx.resources.green;
let serial_port = cx.resources.serial_port;
let usb_dev = cx.resources.usb_dev;
usb_dev.poll(&mut [serial_port]);
if !configured.load(Ordering::Relaxed) {
if usb_dev.state() == UsbDeviceState::Configured {
// off
green.set_high().ok();
configured.store(true, Ordering::Relaxed);
let _ = serial_port.write(b"bChannel: 20\nTX power: +8 dBm\n");
}
} else {
// blink until configured
if green.is_set_low() == Ok(true) {
green.set_high().ok();
} else {
green.set_low().ok();
}
}
// FIXME `hal::Usbd` is not clearing all EVENTS?
let usbd: USBD = unsafe { core::mem::transmute(()) };
if usbd.events_epdata.read().bits() != 0 && usbd.epdatastatus.read().bits() == 0 {
usbd.events_epdata.reset();
}
if usbd.events_sof.read().bits() != 0 {
usbd.events_sof.reset();
}
// usbd.events_endepout[0].reset();
// usbd.events_endepout[1].reset();
// usbd.events_endepout[2].reset();
// usbd.events_ep0setup.reset();
// usbd.events_ep0datadone.reset();
// usbd.events_epdata.reset();
// usbd.events_usbevent.reset();
// usbd.events_usbreset.reset();
}
};

View file

@ -1,63 +0,0 @@
//! Test program, mainly for debugging purposes
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::digital::v2::{OutputPin as _, StatefulOutputPin as _};
use hal::{
clocks::Clocks,
gpio::{p0, Level},
ieee802154::{Packet, Radio},
target as pac,
};
use panic_halt as _;
#[entry]
fn main() -> ! {
let periph = pac::Peripherals::take().unwrap();
let clocks = Clocks::new(periph.CLOCK);
let clocks = clocks.enable_ext_hfosc();
let port = p0::Parts::new(periph.P0);
// NOTE LEDs turn on when the output level is low (0V)
let mut green = port.p0_06.into_push_pull_output(Level::High); // LD1
let mut blue = port.p0_12.into_push_pull_output(Level::High); // LD2 (RGB LED)
let mut red = port.p0_08.into_push_pull_output(Level::High); // LD2 (RGB LED)
let mut radio = Radio::init(periph.RADIO, &clocks);
// turn on green LED to indicate the radio has been initialized
green.set_low().ok();
// set TX power to its maximum value
radio.set_txpower(8);
let mut packet = Packet::new();
loop {
let res = radio.recv(&mut packet);
if res.is_ok() {
// CRC check passed
// clear visual error state (turn off the red LED)
red.set_high().ok();
// toggle blue LED on each successfully received packet
if blue.is_set_low() == Ok(true) {
blue.set_high().ok();
} else {
blue.set_low().ok();
}
// return packet with the contents unchanged
radio.send(&packet);
} else {
// CRC check failed
// indicate error using the red LED
red.set_low().ok();
}
}
}

View file

@ -1,96 +0,0 @@
//! Test program used to debug the `serial-term` tool
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin as _;
use hal::{
clocks::Clocks,
gpio::{p0, Level},
target as pac,
usbd::Usbd,
};
use panic_halt as _;
use usb_device::device::{UsbDeviceBuilder, UsbDeviceState, UsbVidPid};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
#[entry]
fn main() -> ! {
static mut EP_BUF: [u8; 1024] = [0; 1024];
let periph = pac::Peripherals::take().unwrap();
let clocks = Clocks::new(periph.CLOCK);
let clocks = clocks.enable_ext_hfosc();
let port = p0::Parts::new(periph.P0);
// NOTE LEDs turn on when the output level is low (0V)
let mut green = port.p0_06.into_push_pull_output(Level::High); // LD1
let mut blue = port.p0_12.into_push_pull_output(Level::High); // LD2 (RGB LED)
let mut red = port.p0_08.into_push_pull_output(Level::High); // LD2 (RGB LED)
// these loops should always terminate
// detected USB power? (device is USB powered)
while !periph
.POWER
.usbregstatus
.read()
.vbusdetect()
.is_vbus_present()
{
continue;
}
// wait until USB 3.3V supply (internal regulator) is stable
while !periph
.POWER
.events_usbpwrrdy
.read()
.events_usbpwrrdy()
.bit_is_clear()
{
continue;
}
// turn on green LED to show the program is working
green.set_low().ok();
let usb_bus = Usbd::new_alloc(periph.USBD, EP_BUF, &clocks);
let mut serial_port = SerialPort::new(&usb_bus);
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(consts::VID, consts::PID))
.device_class(USB_CLASS_CDC)
.max_packet_size_0(64) // (makes control transfers 8x faster)
.build();
let mut buf = [0; 64];
let mut once = true;
loop {
if !usb_dev.poll(&mut [&mut serial_port]) {
continue;
}
if usb_dev.state() == UsbDeviceState::Configured {
// turn on the blue LED to show the device has been configured
blue.set_low().ok();
if once {
once = false;
serial_port.write(b"Hello, world!\n").ok();
serial_port.flush().ok();
}
if serial_port.read(&mut buf).is_ok() {
// received data from the PC. I'm interpreting this as an error but it may actually
// be part of the CDC/ACM protocol? -- we never send data to the device
red.set_low().ok();
}
} else {
// otherwise turn it off
blue.set_high().ok();
}
}
}