Adding wip changes to ethernet interface

This commit is contained in:
Ryan Summers 2020-06-03 15:46:18 +02:00
parent b39de7f414
commit d7bdafeff2
6 changed files with 136 additions and 66 deletions

View File

@ -1,5 +1,5 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))'] [target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "gdb-multiarch -q -x openocd.gdb" runner = "gdb-multiarch -q -x bmp.gdb"
rustflags = ["-C", "link-arg=-Tlink.x"] rustflags = ["-C", "link-arg=-Tlink.x"]
[build] [build]

View File

@ -33,7 +33,7 @@ log = "0.4"
panic-semihosting = { version = "0.5", optional = true } panic-semihosting = { version = "0.5", optional = true }
panic-halt = "0.2" panic-halt = "0.2"
serde = { version = "1.0", features = ["derive"], default-features = false } serde = { version = "1.0", features = ["derive"], default-features = false }
heapless = "0.5" heapless = "0.5.4"
serde-json-core = "0.1" serde-json-core = "0.1"
cortex-m-rtfm = "0.5" cortex-m-rtfm = "0.5"
embedded-hal = "0.2.3" embedded-hal = "0.2.3"

View File

@ -1,6 +1,7 @@
use embedded_hal; use embedded_hal;
use serde::{Serialize, Deserialize};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum Gain { pub enum Gain {
G1 = 0b00, G1 = 0b00,
G2 = 0b01, G2 = 0b01,

View File

@ -39,6 +39,12 @@ use stm32h7xx_hal::{
prelude::*, prelude::*,
stm32 as pac, stm32 as pac,
}; };
use pounder::Error;
use heapless::{
String,
consts::*,
};
use embedded_hal::{ use embedded_hal::{
digital::v2::OutputPin, digital::v2::OutputPin,
@ -111,12 +117,64 @@ type AFE2 = afe::ProgrammableGainAmplifier<
hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>, hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>,
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>>; hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>>;
macro_rules! route_request {
($request:ident, $buffer:ident,
readable_attributes: [$(($read_attribute:tt, $getter:tt)),*],
modifiable_attributes: [$(($write_attribute:tt, $TYPE:ty, $setter:tt)),*]) => {
match $request {
server::Request::Read{attribute} => {
match attribute {
$(
&$read_attribute => {
let value = match $getter() {
Ok(data) => data,
Err(_) => return server::Response::error(attribute,
"Failed to set attribute"),
};
$buffer = match serde_json_core::to_string(&value) {
Ok(data) => data,
Err(_) => return server::Response::error(attribute,
"Failed to encode attribute value"),
};
server::Response::success(attribute, &$buffer)
},
)*
_ => server::Response::error(attribute, "Unknown attribute")
}
},
server::Request::Write{attribute, value} => {
match attribute {
$(
&$write_attribute => {
let new_value = match serde_json_core::from_str::<$TYPE>(value) {
Ok(data) => data,
Err(_) => return server::Response::error(attribute,
"Failed to decode value"),
};
match $setter(new_value) {
Ok(_) => server::Response::success(attribute, value),
Err(_) => server::Response::error(attribute,
"Failed to set attribute"),
}
}
)*
_ => server::Response::error(attribute, "Unknown attribute")
}
}
}
}
}
#[rtfm::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)] #[rtfm::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)]
const APP: () = { const APP: () = {
struct Resources { struct Resources {
adc1: hal::spi::Spi<hal::stm32::SPI2>, adc1: hal::spi::Spi<hal::stm32::SPI2>,
dac1: hal::spi::Spi<hal::stm32::SPI4>, dac1: hal::spi::Spi<hal::stm32::SPI4>,
_afe1: AFE1, afe1: AFE1,
adc2: hal::spi::Spi<hal::stm32::SPI3>, adc2: hal::spi::Spi<hal::stm32::SPI3>,
dac2: hal::spi::Spi<hal::stm32::SPI5>, dac2: hal::spi::Spi<hal::stm32::SPI5>,
@ -446,7 +504,7 @@ const APP: () = {
dac1: dac1_spi, dac1: dac1_spi,
adc2: adc2_spi, adc2: adc2_spi,
dac2: dac2_spi, dac2: dac2_spi,
_afe1: afe1, afe1: afe1,
_afe2: afe2, _afe2: afe2,
dbg_pin: debug_pin, dbg_pin: debug_pin,
@ -504,7 +562,7 @@ const APP: () = {
cortex_m::asm::bkpt(); cortex_m::asm::bkpt();
} }
#[idle(resources=[net_interface, mac_addr, iir_state, iir_ch])] #[idle(resources=[net_interface, mac_addr, iir_state, iir_ch, afe1])]
fn idle(mut c: idle::Context) -> ! { fn idle(mut c: idle::Context) -> ! {
let mut socket_set_entries: [_; 8] = Default::default(); let mut socket_set_entries: [_; 8] = Default::default();
@ -536,6 +594,8 @@ const APP: () = {
// TODO: Replace with reference to CPU clock from CCDR. // TODO: Replace with reference to CPU clock from CCDR.
next_ms += 400_000.cycles(); next_ms += 400_000.cycles();
let buffer: String<U512> = String::new();
loop { loop {
let tick = Instant::now() > next_ms; let tick = Instant::now() > next_ms;
@ -574,12 +634,16 @@ const APP: () = {
.listen(1235) .listen(1235)
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e)); .unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
} else { } else {
server.poll(socket, |req: &server::Request| { server.poll(socket, |req| {
if req.channel < 2 { info!("Got request: {:?}", req);
c.resources.iir_ch.lock(|iir_ch| { route_request!(req, buffer,
iir_ch[req.channel as usize] = req.iir readable_attributes: [
}); ("stabilizer/afe0/gain", (|| Ok::<afe::Gain, ()>(c.resources.afe1.get_gain())))
} ],
modifiable_attributes: [
("stabilizer/afe0/gain", afe::Gain, (|gain| Ok::<(), ()>(c.resources.afe1.set_gain(gain))))
]
)
}); });
} }
} }

View File

@ -1,14 +1,14 @@
use mcp23017; use mcp23017;
use ad9959; use ad9959;
pub mod error; mod error;
pub mod attenuators; pub mod attenuators;
mod rf_power; mod rf_power;
pub mod types; pub mod types;
use super::hal; use super::hal;
use error::Error; pub use error::Error;
use attenuators::AttenuatorInterface; use attenuators::AttenuatorInterface;
use types::{DdsChannel, InputChannel}; use types::{DdsChannel, InputChannel};
use rf_power::PowerMeasurementInterface; use rf_power::PowerMeasurementInterface;

View File

@ -8,7 +8,6 @@ use core::fmt::Write;
use serde::{ use serde::{
de::DeserializeOwned,
Deserialize, Deserialize,
Serialize Serialize
}; };
@ -19,18 +18,43 @@ use serde_json_core::{
}; };
use super::net; use super::net;
use super::iir::IIR;
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize, Debug)]
pub struct Request { pub enum Request<'a, 'b> {
pub channel: u8, Read{attribute: &'a str},
pub iir: IIR, Write{attribute: &'a str, value: &'b str},
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct Response<'a> { pub struct Response<'a, 'b> {
code: i32, code: i32,
message: &'a str, attribute: &'a str,
value: &'b str,
}
impl<'a, 'b> Response<'a, 'b> {
pub fn success<'c, 'd>(attribute: &'c str, value: &'d str) -> Self
where
'c: 'a,
'd: 'b,
{
Self { code: 200, attribute: attribute, value: value}
}
pub fn error<'c, 'd>(attribute: &'c str, message: &'d str) -> Self
where
'c: 'a,
'd: 'b,
{
Self { code: 400, attribute: attribute, value: message}
}
pub fn custom<'c>(code: i32, message : &'c str) -> Self
where
'c: 'b,
{
Self { code: code, attribute: "", value: message}
}
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -61,73 +85,54 @@ impl Server {
} }
} }
pub fn poll<T, F, R>( pub fn poll<'a, 'b, F>(
&mut self, &mut self,
socket: &mut net::socket::TcpSocket, socket: &mut net::socket::TcpSocket,
f: F, f: F,
) -> Option<R> )
where where
T: DeserializeOwned, F: FnOnce(&Request) -> Response<'a, 'b>
F: FnOnce(&T) -> R,
{ {
while socket.can_recv() { while socket.can_recv() {
let found = socket let found = socket.recv(|buf| {
.recv(|buf| { let (len, found) =
let (len, found) = match buf.iter().position(|&c| c as char == '\n') {
match buf.iter().position(|&c| c as char == '\n') { Some(end) => (end + 1, true),
Some(end) => (end + 1, true), None => (buf.len(), false),
None => (buf.len(), false), };
}; if self.data.len() + len >= self.data.capacity() {
if self.data.len() + len >= self.data.capacity() { self.discard = true;
self.discard = true; self.data.clear();
self.data.clear(); } else if !self.discard && len > 0 {
} else if !self.discard && len > 0 { self.data.extend_from_slice(&buf[..len]).unwrap();
self.data.extend_from_slice(&buf[..len]).unwrap(); }
} (len, found)
(len, found) }).unwrap();
})
.unwrap();
if found { if found {
if self.discard { if self.discard {
self.discard = false; self.discard = false;
json_reply( json_reply(socket, &Response::custom(520, "command buffer overflow"),
socket,
&Response {
code: 520,
message: "command buffer overflow",
},
); );
self.data.clear(); self.data.clear();
} else { } else {
let r = from_slice::<T>(&self.data[..self.data.len() - 1]); let r = from_slice::<Request>(&self.data[..self.data.len() - 1]);
self.data.clear(); self.data.clear();
match r { match r {
Ok(res) => { Ok(res) => {
let r = f(&res); let response = f(&res);
json_reply( json_reply(socket, &response);
socket, return;
&Response { },
code: 200,
message: "ok",
},
);
return Some(r);
}
Err(err) => { Err(err) => {
warn!("parse error {:?}", err); warn!("parse error {:?}", err);
json_reply( json_reply(socket, &Response::custom(550, "parse error"),
socket,
&Response {
code: 550,
message: "parse error",
},
); );
} }
} }
} }
} }
} }
None
} }
} }