Adding wip changes to ethernet interface

master
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"))']
runner = "gdb-multiarch -q -x openocd.gdb"
runner = "gdb-multiarch -q -x bmp.gdb"
rustflags = ["-C", "link-arg=-Tlink.x"]
[build]

View File

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

View File

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

View File

@ -39,6 +39,12 @@ use stm32h7xx_hal::{
prelude::*,
stm32 as pac,
};
use pounder::Error;
use heapless::{
String,
consts::*,
};
use embedded_hal::{
digital::v2::OutputPin,
@ -111,12 +117,64 @@ type AFE2 = afe::ProgrammableGainAmplifier<
hal::gpio::gpiod::PD14<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)]
const APP: () = {
struct Resources {
adc1: hal::spi::Spi<hal::stm32::SPI2>,
dac1: hal::spi::Spi<hal::stm32::SPI4>,
_afe1: AFE1,
afe1: AFE1,
adc2: hal::spi::Spi<hal::stm32::SPI3>,
dac2: hal::spi::Spi<hal::stm32::SPI5>,
@ -446,7 +504,7 @@ const APP: () = {
dac1: dac1_spi,
adc2: adc2_spi,
dac2: dac2_spi,
_afe1: afe1,
afe1: afe1,
_afe2: afe2,
dbg_pin: debug_pin,
@ -504,7 +562,7 @@ const APP: () = {
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) -> ! {
let mut socket_set_entries: [_; 8] = Default::default();
@ -536,6 +594,8 @@ const APP: () = {
// TODO: Replace with reference to CPU clock from CCDR.
next_ms += 400_000.cycles();
let buffer: String<U512> = String::new();
loop {
let tick = Instant::now() > next_ms;
@ -574,12 +634,16 @@ const APP: () = {
.listen(1235)
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
} else {
server.poll(socket, |req: &server::Request| {
if req.channel < 2 {
c.resources.iir_ch.lock(|iir_ch| {
iir_ch[req.channel as usize] = req.iir
});
}
server.poll(socket, |req| {
info!("Got request: {:?}", req);
route_request!(req, buffer,
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 ad9959;
pub mod error;
mod error;
pub mod attenuators;
mod rf_power;
pub mod types;
use super::hal;
use error::Error;
pub use error::Error;
use attenuators::AttenuatorInterface;
use types::{DdsChannel, InputChannel};
use rf_power::PowerMeasurementInterface;

View File

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