2019-11-11 19:04:50 +08:00
|
|
|
#![deny(warnings)]
|
2019-11-24 22:04:29 +08:00
|
|
|
#![allow(clippy::missing_safety_doc)]
|
2019-03-18 19:56:26 +08:00
|
|
|
#![no_std]
|
|
|
|
#![no_main]
|
2019-10-22 21:43:49 +08:00
|
|
|
#![cfg_attr(feature = "nightly", feature(asm))]
|
2019-03-18 19:56:26 +08:00
|
|
|
// Enable returning `!`
|
2019-10-22 21:43:49 +08:00
|
|
|
#![cfg_attr(feature = "nightly", feature(never_type))]
|
|
|
|
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
|
2019-03-18 19:56:26 +08:00
|
|
|
|
2019-06-07 17:26:24 +08:00
|
|
|
#[inline(never)]
|
|
|
|
#[panic_handler]
|
2019-10-22 21:43:49 +08:00
|
|
|
#[cfg(all(feature = "nightly", not(feature = "semihosting")))]
|
2019-06-07 17:26:24 +08:00
|
|
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
2019-06-07 22:28:22 +08:00
|
|
|
let gpiod = unsafe { &*pac::GPIOD::ptr() };
|
2019-11-24 22:09:52 +08:00
|
|
|
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high()); // FP_LED_1, FP_LED_3
|
|
|
|
unsafe {
|
|
|
|
core::intrinsics::abort();
|
|
|
|
}
|
2019-06-07 17:26:24 +08:00
|
|
|
}
|
|
|
|
|
2019-03-18 19:56:26 +08:00
|
|
|
#[cfg(feature = "semihosting")]
|
|
|
|
extern crate panic_semihosting;
|
|
|
|
|
2019-10-22 21:43:49 +08:00
|
|
|
#[cfg(not(any(feature = "nightly", feature = "semihosting")))]
|
|
|
|
extern crate panic_halt;
|
|
|
|
|
2019-03-18 19:56:26 +08:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
|
|
|
|
2019-03-19 23:27:22 +08:00
|
|
|
use core::ptr;
|
2019-06-03 23:06:11 +08:00
|
|
|
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
2019-05-24 00:57:00 +08:00
|
|
|
use core::fmt::Write;
|
2019-06-03 23:06:11 +08:00
|
|
|
use cortex_m_rt::exception;
|
2019-11-24 22:09:52 +08:00
|
|
|
use heapless::{consts::*, String, Vec};
|
2019-08-26 21:47:42 +08:00
|
|
|
use rtfm::cyccnt::{Instant, U32Ext as _};
|
2020-04-18 16:54:55 +08:00
|
|
|
use stm32h7::stm32h743v as pac;
|
2019-03-18 19:56:26 +08:00
|
|
|
|
2019-04-23 03:31:59 +08:00
|
|
|
use smoltcp as net;
|
|
|
|
|
2019-11-24 22:09:52 +08:00
|
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
|
|
use serde_json_core::{de::from_slice, ser::to_string};
|
2019-05-24 00:57:00 +08:00
|
|
|
|
2019-04-23 03:31:59 +08:00
|
|
|
mod eth;
|
|
|
|
|
2019-03-28 02:48:22 +08:00
|
|
|
mod iir;
|
|
|
|
use iir::*;
|
|
|
|
|
2019-11-14 04:33:14 +08:00
|
|
|
mod board;
|
2019-11-24 22:09:52 +08:00
|
|
|
mod eeprom;
|
|
|
|
mod i2c;
|
2019-09-05 07:54:00 +08:00
|
|
|
|
2019-03-18 19:56:26 +08:00
|
|
|
#[cfg(not(feature = "semihosting"))]
|
|
|
|
fn init_log() {}
|
|
|
|
|
|
|
|
#[cfg(feature = "semihosting")]
|
|
|
|
fn init_log() {
|
2019-11-24 22:09:52 +08:00
|
|
|
use cortex_m_log::log::{init as init_log, Logger};
|
|
|
|
use cortex_m_log::printer::semihosting::{hio::HStdout, InterruptOk};
|
2019-03-18 19:56:26 +08:00
|
|
|
use log::LevelFilter;
|
|
|
|
static mut LOGGER: Option<Logger<InterruptOk<HStdout>>> = None;
|
|
|
|
let logger = Logger {
|
2019-04-13 00:13:18 +08:00
|
|
|
inner: InterruptOk::<_>::stdout().unwrap(),
|
2019-03-18 19:56:26 +08:00
|
|
|
level: LevelFilter::Info,
|
|
|
|
};
|
2019-11-24 22:09:52 +08:00
|
|
|
let logger = unsafe { LOGGER.get_or_insert(logger) };
|
2019-03-18 19:56:26 +08:00
|
|
|
|
2019-05-31 00:03:48 +08:00
|
|
|
init_log(logger).unwrap();
|
2019-03-18 19:56:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Pull in build information (from `built` crate)
|
|
|
|
mod build_info {
|
|
|
|
#![allow(dead_code)]
|
2019-05-24 00:57:00 +08:00
|
|
|
// include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
2019-03-18 19:56:26 +08:00
|
|
|
}
|
|
|
|
|
2019-05-31 00:03:48 +08:00
|
|
|
const SCALE: f32 = ((1 << 15) - 1) as f32;
|
2019-03-25 17:08:27 +08:00
|
|
|
|
2019-06-03 23:06:11 +08:00
|
|
|
// static ETHERNET_PENDING: AtomicBool = AtomicBool::new(true);
|
2019-04-23 03:31:59 +08:00
|
|
|
|
2019-04-30 19:42:05 +08:00
|
|
|
const TCP_RX_BUFFER_SIZE: usize = 8192;
|
|
|
|
const TCP_TX_BUFFER_SIZE: usize = 8192;
|
2019-04-23 03:31:59 +08:00
|
|
|
|
|
|
|
macro_rules! create_socket {
|
2019-11-24 22:09:52 +08:00
|
|
|
($set:ident, $rx_storage:ident, $tx_storage:ident, $target:ident) => {
|
2019-04-23 03:31:59 +08:00
|
|
|
let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
|
|
|
let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
2019-11-24 22:09:52 +08:00
|
|
|
let tcp_rx_buffer =
|
|
|
|
net::socket::TcpSocketBuffer::new(&mut $rx_storage[..]);
|
|
|
|
let tcp_tx_buffer =
|
|
|
|
net::socket::TcpSocketBuffer::new(&mut $tx_storage[..]);
|
|
|
|
let tcp_socket =
|
|
|
|
net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
2019-04-23 03:31:59 +08:00
|
|
|
let $target = $set.add(tcp_socket);
|
2019-11-24 22:09:52 +08:00
|
|
|
};
|
2019-04-23 03:31:59 +08:00
|
|
|
}
|
|
|
|
|
2020-04-18 16:54:55 +08:00
|
|
|
#[rtfm::app(device = stm32h7::stm32h743v, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)]
|
2019-05-31 00:03:48 +08:00
|
|
|
const APP: () = {
|
2019-08-26 21:47:42 +08:00
|
|
|
struct Resources {
|
|
|
|
spi: (pac::SPI1, pac::SPI2, pac::SPI4, pac::SPI5),
|
2019-09-05 07:54:00 +08:00
|
|
|
i2c: pac::I2C2,
|
2019-11-24 22:09:52 +08:00
|
|
|
ethernet_periph:
|
|
|
|
(pac::ETHERNET_MAC, pac::ETHERNET_DMA, pac::ETHERNET_MTL),
|
2019-08-26 21:47:42 +08:00
|
|
|
#[init([[0.; 5]; 2])]
|
|
|
|
iir_state: [IIRState; 2],
|
2019-11-24 21:10:01 +08:00
|
|
|
#[init([IIR { ba: [1., 0., 0., 0., 0.], y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; 2])]
|
2019-08-26 21:47:42 +08:00
|
|
|
iir_ch: [IIR; 2],
|
|
|
|
#[link_section = ".sram3.eth"]
|
|
|
|
#[init(eth::Device::new())]
|
|
|
|
ethernet: eth::Device,
|
|
|
|
}
|
2019-05-31 00:03:48 +08:00
|
|
|
|
2019-05-31 00:18:59 +08:00
|
|
|
#[init(schedule = [tick])]
|
2019-05-31 00:03:48 +08:00
|
|
|
fn init(c: init::Context) -> init::LateResources {
|
2019-11-14 04:33:14 +08:00
|
|
|
board::init();
|
2019-05-31 00:03:48 +08:00
|
|
|
|
|
|
|
init_log();
|
|
|
|
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
|
|
|
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
|
|
|
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
|
|
|
|
|
2019-08-26 21:47:42 +08:00
|
|
|
// c.schedule.tick(Instant::now()).unwrap();
|
2019-05-31 04:57:41 +08:00
|
|
|
|
2019-11-14 04:33:14 +08:00
|
|
|
let dp = c.device;
|
2019-05-31 04:57:41 +08:00
|
|
|
init::LateResources {
|
2019-11-14 04:33:14 +08:00
|
|
|
spi: (dp.SPI1, dp.SPI2, dp.SPI4, dp.SPI5),
|
|
|
|
i2c: dp.I2C2,
|
2019-11-24 22:09:52 +08:00
|
|
|
ethernet_periph: (
|
|
|
|
dp.ETHERNET_MAC,
|
|
|
|
dp.ETHERNET_DMA,
|
|
|
|
dp.ETHERNET_MTL,
|
|
|
|
),
|
2019-05-31 04:57:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-05 07:54:00 +08:00
|
|
|
#[idle(resources = [ethernet, ethernet_periph, iir_state, iir_ch, i2c])]
|
2019-05-31 04:57:41 +08:00
|
|
|
fn idle(c: idle::Context) -> ! {
|
2019-08-26 21:47:42 +08:00
|
|
|
let (MAC, DMA, MTL) = c.resources.ethernet_periph;
|
2019-05-31 04:57:41 +08:00
|
|
|
|
2019-09-05 07:54:00 +08:00
|
|
|
let hardware_addr = match eeprom::read_eui48(c.resources.i2c) {
|
|
|
|
Err(_) => {
|
|
|
|
info!("Could not read EEPROM, using default MAC address");
|
|
|
|
net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00])
|
2019-11-24 22:09:52 +08:00
|
|
|
}
|
|
|
|
Ok(raw_mac) => net::wire::EthernetAddress(raw_mac),
|
2019-09-05 07:54:00 +08:00
|
|
|
};
|
|
|
|
info!("MAC: {}", hardware_addr);
|
|
|
|
|
2019-08-26 21:47:42 +08:00
|
|
|
unsafe { c.resources.ethernet.init(hardware_addr, MAC, DMA, MTL) };
|
2019-05-31 00:03:48 +08:00
|
|
|
let mut neighbor_cache_storage = [None; 8];
|
2019-11-24 22:09:52 +08:00
|
|
|
let neighbor_cache =
|
|
|
|
net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
|
2019-05-31 00:03:48 +08:00
|
|
|
let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99);
|
|
|
|
let mut ip_addrs = [net::wire::IpCidr::new(local_addr, 24)];
|
2019-11-24 22:09:52 +08:00
|
|
|
let mut iface =
|
|
|
|
net::iface::EthernetInterfaceBuilder::new(c.resources.ethernet)
|
|
|
|
.ethernet_addr(hardware_addr)
|
|
|
|
.neighbor_cache(neighbor_cache)
|
|
|
|
.ip_addrs(&mut ip_addrs[..])
|
|
|
|
.finalize();
|
2019-05-31 00:03:48 +08:00
|
|
|
let mut socket_set_entries: [_; 8] = Default::default();
|
2019-11-24 22:09:52 +08:00
|
|
|
let mut sockets =
|
|
|
|
net::socket::SocketSet::new(&mut socket_set_entries[..]);
|
2019-05-31 00:03:48 +08:00
|
|
|
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0);
|
|
|
|
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle1);
|
|
|
|
|
2019-05-31 04:57:41 +08:00
|
|
|
// unsafe { eth::enable_interrupt(DMA); }
|
2019-06-03 23:06:11 +08:00
|
|
|
let mut time = 0u32;
|
2019-08-26 21:47:42 +08:00
|
|
|
let mut next_ms = Instant::now();
|
2019-09-12 07:35:00 +08:00
|
|
|
next_ms += 400_000.cycles();
|
2019-06-03 23:06:11 +08:00
|
|
|
let mut server = Server::new();
|
2019-08-26 21:47:42 +08:00
|
|
|
let mut iir_state: resources::iir_state = c.resources.iir_state;
|
|
|
|
let mut iir_ch: resources::iir_ch = c.resources.iir_ch;
|
2019-05-31 00:03:48 +08:00
|
|
|
loop {
|
2019-05-31 04:57:41 +08:00
|
|
|
// if ETHERNET_PENDING.swap(false, Ordering::Relaxed) { }
|
2019-08-26 21:47:42 +08:00
|
|
|
let tick = Instant::now() > next_ms;
|
2019-06-03 23:06:11 +08:00
|
|
|
if tick {
|
2019-09-12 07:35:00 +08:00
|
|
|
next_ms += 400_000.cycles();
|
2019-05-31 04:57:41 +08:00
|
|
|
time += 1;
|
|
|
|
}
|
|
|
|
{
|
2019-11-24 22:09:52 +08:00
|
|
|
let socket =
|
|
|
|
&mut *sockets.get::<net::socket::TcpSocket>(tcp_handle0);
|
2019-06-03 23:06:11 +08:00
|
|
|
if socket.state() == net::socket::TcpState::CloseWait {
|
|
|
|
socket.close();
|
|
|
|
} else if !(socket.is_open() || socket.is_listening()) {
|
2019-11-24 22:09:52 +08:00
|
|
|
socket
|
|
|
|
.listen(1234)
|
|
|
|
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
|
2019-06-03 23:06:11 +08:00
|
|
|
} else if tick && socket.can_send() {
|
2019-05-31 05:50:18 +08:00
|
|
|
let s = iir_state.lock(|iir_state| Status {
|
|
|
|
t: time,
|
|
|
|
x0: iir_state[0][0],
|
|
|
|
y0: iir_state[0][2],
|
|
|
|
x1: iir_state[1][0],
|
2019-11-24 22:09:52 +08:00
|
|
|
y1: iir_state[1][2],
|
2019-05-31 05:50:18 +08:00
|
|
|
});
|
2019-06-03 23:06:11 +08:00
|
|
|
json_reply(socket, &s);
|
2019-05-31 04:57:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2019-11-24 22:09:52 +08:00
|
|
|
let socket =
|
|
|
|
&mut *sockets.get::<net::socket::TcpSocket>(tcp_handle1);
|
2019-06-03 23:06:11 +08:00
|
|
|
if socket.state() == net::socket::TcpState::CloseWait {
|
|
|
|
socket.close();
|
|
|
|
} else if !(socket.is_open() || socket.is_listening()) {
|
2019-11-24 22:09:52 +08:00
|
|
|
socket
|
|
|
|
.listen(1235)
|
|
|
|
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
|
2019-05-31 04:57:41 +08:00
|
|
|
} else {
|
2019-06-03 23:54:35 +08:00
|
|
|
server.poll(socket, |req: &Request| {
|
2019-06-03 23:06:11 +08:00
|
|
|
if req.channel < 2 {
|
2019-11-24 22:09:52 +08:00
|
|
|
iir_ch.lock(|iir_ch| {
|
|
|
|
iir_ch[req.channel as usize] = req.iir
|
|
|
|
});
|
2019-06-03 23:06:11 +08:00
|
|
|
}
|
|
|
|
});
|
2019-05-31 04:57:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-24 22:09:52 +08:00
|
|
|
if !match iface.poll(
|
|
|
|
&mut sockets,
|
|
|
|
net::time::Instant::from_millis(time as i64),
|
|
|
|
) {
|
2019-05-31 04:57:41 +08:00
|
|
|
Ok(changed) => changed,
|
|
|
|
Err(net::Error::Unrecognized) => true,
|
2019-11-24 22:09:52 +08:00
|
|
|
Err(e) => {
|
|
|
|
info!("iface poll error: {:?}", e);
|
|
|
|
true
|
|
|
|
}
|
2019-05-31 04:57:41 +08:00
|
|
|
} {
|
|
|
|
// cortex_m::asm::wfi();
|
|
|
|
}
|
2019-05-31 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
2019-04-28 19:37:14 +08:00
|
|
|
|
2019-05-31 05:50:18 +08:00
|
|
|
#[task(priority = 1, schedule = [tick])]
|
2019-05-31 00:18:59 +08:00
|
|
|
fn tick(c: tick::Context) {
|
2019-05-31 04:57:41 +08:00
|
|
|
static mut TIME: u32 = 0;
|
|
|
|
*TIME += 1;
|
2019-05-31 00:18:59 +08:00
|
|
|
const PERIOD: u32 = 200_000_000;
|
|
|
|
c.schedule.tick(c.scheduled + PERIOD.cycles()).unwrap();
|
|
|
|
}
|
|
|
|
|
2019-05-31 00:03:48 +08:00
|
|
|
// seems to slow it down
|
|
|
|
// #[link_section = ".data.spi1"]
|
2019-08-26 21:47:42 +08:00
|
|
|
#[task(binds = SPI1, resources = [spi, iir_state, iir_ch], priority = 2)]
|
|
|
|
fn spi1(c: spi1::Context) {
|
2019-05-31 00:03:48 +08:00
|
|
|
#[cfg(feature = "bkpt")]
|
|
|
|
cortex_m::asm::bkpt();
|
2019-08-26 21:47:42 +08:00
|
|
|
let (spi1, spi2, spi4, spi5) = c.resources.spi;
|
|
|
|
let iir_ch = c.resources.iir_ch;
|
|
|
|
let iir_state = c.resources.iir_state;
|
2019-05-31 00:03:48 +08:00
|
|
|
|
|
|
|
let sr = spi1.sr.read();
|
|
|
|
if sr.eot().bit_is_set() {
|
2019-05-31 04:57:41 +08:00
|
|
|
spi1.ifcr.write(|w| w.eotc().set_bit());
|
2019-04-23 03:31:59 +08:00
|
|
|
}
|
2019-05-31 00:03:48 +08:00
|
|
|
if sr.rxp().bit_is_set() {
|
|
|
|
let rxdr = &spi1.rxdr as *const _ as *const u16;
|
|
|
|
let a = unsafe { ptr::read_volatile(rxdr) };
|
|
|
|
let x0 = f32::from(a as i16);
|
2019-05-31 00:18:59 +08:00
|
|
|
let y0 = iir_ch[0].update(&mut iir_state[0], x0);
|
2019-05-31 00:03:48 +08:00
|
|
|
let d = y0 as i16 as u16 ^ 0x8000;
|
|
|
|
let txdr = &spi2.txdr as *const _ as *mut u16;
|
|
|
|
unsafe { ptr::write_volatile(txdr, d) };
|
2019-05-28 02:43:39 +08:00
|
|
|
}
|
|
|
|
|
2019-05-31 00:03:48 +08:00
|
|
|
let sr = spi5.sr.read();
|
|
|
|
if sr.eot().bit_is_set() {
|
2019-05-31 04:57:41 +08:00
|
|
|
spi5.ifcr.write(|w| w.eotc().set_bit());
|
2019-04-23 03:31:59 +08:00
|
|
|
}
|
2019-05-31 00:03:48 +08:00
|
|
|
if sr.rxp().bit_is_set() {
|
|
|
|
let rxdr = &spi5.rxdr as *const _ as *const u16;
|
|
|
|
let a = unsafe { ptr::read_volatile(rxdr) };
|
|
|
|
let x0 = f32::from(a as i16);
|
2019-05-31 00:18:59 +08:00
|
|
|
let y0 = iir_ch[1].update(&mut iir_state[1], x0);
|
2019-05-31 00:03:48 +08:00
|
|
|
let d = y0 as i16 as u16 ^ 0x8000;
|
|
|
|
let txdr = &spi4.txdr as *const _ as *mut u16;
|
|
|
|
unsafe { ptr::write_volatile(txdr, d) };
|
|
|
|
}
|
|
|
|
#[cfg(feature = "bkpt")]
|
|
|
|
cortex_m::asm::bkpt();
|
2019-03-18 19:56:26 +08:00
|
|
|
}
|
2019-05-31 00:03:48 +08:00
|
|
|
|
2019-05-31 04:57:41 +08:00
|
|
|
/*
|
2019-08-26 21:47:42 +08:00
|
|
|
#[task(binds = ETH, resources = [ethernet_periph], priority = 1)]
|
|
|
|
fn eth(c: eth::Context) {
|
|
|
|
let dma = &c.resources.ethernet_periph.1;
|
2019-05-31 00:03:48 +08:00
|
|
|
ETHERNET_PENDING.store(true, Ordering::Relaxed);
|
|
|
|
unsafe { eth::interrupt_handler(dma) }
|
|
|
|
}
|
2019-05-31 04:57:41 +08:00
|
|
|
*/
|
2019-05-31 00:03:48 +08:00
|
|
|
|
|
|
|
extern "C" {
|
2019-05-31 04:57:41 +08:00
|
|
|
// hw interrupt handlers for RTFM to use for scheduling tasks
|
|
|
|
// one per priority
|
2019-05-31 00:03:48 +08:00
|
|
|
fn DCMI();
|
|
|
|
fn JPEG();
|
|
|
|
fn SDMMC();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-11-24 22:09:52 +08:00
|
|
|
#[derive(Deserialize, Serialize)]
|
2019-05-28 02:43:39 +08:00
|
|
|
struct Request {
|
2019-05-28 18:15:15 +08:00
|
|
|
channel: u8,
|
2019-05-24 00:57:00 +08:00
|
|
|
iir: IIR,
|
|
|
|
}
|
|
|
|
|
2019-05-28 02:43:39 +08:00
|
|
|
#[derive(Serialize)]
|
|
|
|
struct Response<'a> {
|
|
|
|
code: i32,
|
|
|
|
message: &'a str,
|
|
|
|
}
|
|
|
|
|
2019-05-31 04:57:41 +08:00
|
|
|
#[derive(Serialize)]
|
|
|
|
struct Status {
|
|
|
|
t: u32,
|
|
|
|
x0: f32,
|
|
|
|
y0: f32,
|
|
|
|
x1: f32,
|
2019-11-24 22:09:52 +08:00
|
|
|
y1: f32,
|
2019-05-28 02:43:39 +08:00
|
|
|
}
|
|
|
|
|
2019-06-03 23:06:11 +08:00
|
|
|
fn json_reply<T: Serialize>(socket: &mut net::socket::TcpSocket, msg: &T) {
|
2019-05-31 04:57:41 +08:00
|
|
|
let mut u: String<U128> = to_string(msg).unwrap();
|
|
|
|
u.push('\n').unwrap();
|
|
|
|
socket.write_str(&u).unwrap();
|
|
|
|
}
|
|
|
|
|
2019-06-03 23:06:11 +08:00
|
|
|
struct Server {
|
|
|
|
data: Vec<u8, U256>,
|
|
|
|
discard: bool,
|
|
|
|
}
|
|
|
|
|
2019-05-28 18:59:26 +08:00
|
|
|
impl Server {
|
|
|
|
fn new() -> Self {
|
2019-11-24 22:09:52 +08:00
|
|
|
Self {
|
|
|
|
data: Vec::new(),
|
|
|
|
discard: false,
|
|
|
|
}
|
2019-05-28 18:59:26 +08:00
|
|
|
}
|
|
|
|
|
2019-11-24 22:09:52 +08:00
|
|
|
fn poll<T, F, R>(
|
|
|
|
&mut self,
|
|
|
|
socket: &mut net::socket::TcpSocket,
|
|
|
|
f: F,
|
|
|
|
) -> Option<R>
|
|
|
|
where
|
|
|
|
T: DeserializeOwned,
|
|
|
|
F: FnOnce(&T) -> R,
|
2019-06-03 23:54:35 +08:00
|
|
|
{
|
2019-05-28 18:59:26 +08:00
|
|
|
while socket.can_recv() {
|
2019-11-24 22:09:52 +08:00
|
|
|
let found = socket
|
|
|
|
.recv(|buf| {
|
|
|
|
let (len, found) =
|
|
|
|
match buf.iter().position(|&c| c as char == '\n') {
|
|
|
|
Some(end) => (end + 1, true),
|
|
|
|
None => (buf.len(), false),
|
|
|
|
};
|
|
|
|
if self.data.len() + len >= self.data.capacity() {
|
|
|
|
self.discard = true;
|
|
|
|
self.data.clear();
|
|
|
|
} else if !self.discard && len > 0 {
|
|
|
|
self.data.extend_from_slice(&buf[..len]).unwrap();
|
|
|
|
}
|
|
|
|
(len, found)
|
|
|
|
})
|
|
|
|
.unwrap();
|
2019-06-03 23:06:11 +08:00
|
|
|
if found {
|
|
|
|
if self.discard {
|
|
|
|
self.discard = false;
|
2019-11-24 22:09:52 +08:00
|
|
|
json_reply(
|
|
|
|
socket,
|
|
|
|
&Response {
|
|
|
|
code: 520,
|
|
|
|
message: "command buffer overflow",
|
|
|
|
},
|
|
|
|
);
|
2019-06-04 01:08:21 +08:00
|
|
|
self.data.clear();
|
2019-06-03 23:06:11 +08:00
|
|
|
} else {
|
2019-11-13 09:50:18 +08:00
|
|
|
let r = from_slice::<T>(&self.data[..self.data.len() - 1]);
|
2019-06-03 23:06:11 +08:00
|
|
|
self.data.clear();
|
|
|
|
match r {
|
|
|
|
Ok(res) => {
|
2019-06-04 01:08:21 +08:00
|
|
|
let r = f(&res);
|
2019-11-24 22:09:52 +08:00
|
|
|
json_reply(
|
|
|
|
socket,
|
|
|
|
&Response {
|
|
|
|
code: 200,
|
|
|
|
message: "ok",
|
|
|
|
},
|
|
|
|
);
|
2019-06-04 01:08:21 +08:00
|
|
|
return Some(r);
|
2019-11-24 22:09:52 +08:00
|
|
|
}
|
2019-06-03 23:06:11 +08:00
|
|
|
Err(err) => {
|
|
|
|
warn!("parse error {:?}", err);
|
2019-11-24 22:09:52 +08:00
|
|
|
json_reply(
|
|
|
|
socket,
|
|
|
|
&Response {
|
|
|
|
code: 550,
|
|
|
|
message: "parse error",
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2019-06-03 23:06:11 +08:00
|
|
|
}
|
2019-05-28 02:43:39 +08:00
|
|
|
}
|
2019-06-03 23:06:11 +08:00
|
|
|
}
|
2019-05-28 02:43:39 +08:00
|
|
|
}
|
2019-06-04 01:08:21 +08:00
|
|
|
None
|
2019-05-28 02:43:39 +08:00
|
|
|
}
|
|
|
|
}
|
2019-05-24 00:57:00 +08:00
|
|
|
|
2019-03-18 19:56:26 +08:00
|
|
|
#[exception]
|
|
|
|
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
|
|
|
|
panic!("HardFault at {:#?}", ef);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[exception]
|
|
|
|
fn DefaultHandler(irqn: i16) {
|
|
|
|
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
|
|
}
|