From 057d7b47f9a0e08ab846d177156974762370f84b Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Sun, 17 Dec 2023 14:49:52 -0800 Subject: [PATCH 1/5] record sensor min/max values and times --- idl/sensor.idol | 28 ++++++++++++++++ task/sensor/src/main.rs | 72 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/idl/sensor.idol b/idl/sensor.idol index c3261c4e6..917c7d647 100644 --- a/idl/sensor.idol +++ b/idl/sensor.idol @@ -71,6 +71,34 @@ Interface( encoding: Hubpack, idempotent: true, ), + "get_min": ( + description: "returns the minimum value recorded and its timestamp", + args: { + "id": ( + type: "SensorId", + ) + }, + reply: Result( + ok: "(f32, u64)", + err: CLike("SensorApiError"), + ), + encoding: Hubpack, + idempotent: true, + ), + "get_max": ( + description: "returns the maximum value recorded and its timestamp", + args: { + "id": ( + type: "SensorId", + ) + }, + reply: Result( + ok: "(f32, u64)", + err: CLike("SensorApiError"), + ), + encoding: Hubpack, + idempotent: true, + ), "post": ( args: { "id": ( diff --git a/task/sensor/src/main.rs b/task/sensor/src/main.rs index 7d076b33c..60a95ccd8 100644 --- a/task/sensor/src/main.rs +++ b/task/sensor/src/main.rs @@ -59,6 +59,12 @@ struct ServerImpl { data_value: SensorArray, data_time: SensorArray, + min_value: SensorArray, + min_time: SensorArray, + + max_value: SensorArray, + max_time: SensorArray, + err_value: SensorArray, err_time: SensorArray, @@ -136,6 +142,40 @@ impl idl::InOrderSensorImpl for ServerImpl { } } + fn get_min( + &mut self, + _: &RecvMessage, + id: SensorId, + ) -> Result<(f32, u64), RequestError> { + Ok(( + self.min_value + .get(id) + .cloned() + .ok_or(SensorApiError::InvalidSensor)?, + self.min_time + .get(id) + .cloned() + .ok_or(SensorApiError::InvalidSensor)?, + )) + } + + fn get_max( + &mut self, + _: &RecvMessage, + id: SensorId, + ) -> Result<(f32, u64), RequestError> { + Ok(( + self.max_value + .get(id) + .cloned() + .ok_or(SensorApiError::InvalidSensor)?, + self.max_time + .get(id) + .cloned() + .ok_or(SensorApiError::InvalidSensor)?, + )) + } + fn post( &mut self, _: &RecvMessage, @@ -153,6 +193,17 @@ impl idl::InOrderSensorImpl for ServerImpl { self.last_reading[id] = Some(r); self.data_value[id] = value; self.data_time[id] = timestamp; + + if value < self.min_value[id] { + self.min_value[id] = value; + self.min_time[id] = timestamp; + } + + if value > self.max_value[id] { + self.max_value[id] = value; + self.max_time[id] = timestamp; + } + Ok(()) } @@ -238,10 +289,25 @@ fn main() -> ! { // sys_set_timer(Some(deadline), notifications::TIMER_MASK); - let (last_reading, data_value, data_time, err_value, err_time, nerrors) = mutable_statics::mutable_statics! { + let ( + last_reading, + data_value, + data_time, + min_value, + min_time, + max_value, + max_time, + err_value, + err_time, + nerrors, + ) = mutable_statics::mutable_statics! { static mut LAST_READING: [Option; NUM_SENSORS] = [|| None; _]; static mut DATA_VALUE: [f32; NUM_SENSORS] = [|| f32::NAN; _]; static mut DATA_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; + static mut MIN_VALUE: [f32; NUM_SENSORS] = [|| f32::MAX; _]; + static mut MIN_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; + static mut MAX_VALUE: [f32; NUM_SENSORS] = [|| f32::MIN; _]; + static mut MAX_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; static mut ERR_VALUE: [NoData; NUM_SENSORS] = [|| NoData::DeviceUnavailable; _]; static mut ERR_TIME: [u64; NUM_SENSORS] = [|| 0; _]; static mut NERRORS: [u32; NUM_SENSORS] = [|| 0; _]; @@ -251,6 +317,10 @@ fn main() -> ! { last_reading: SensorArray(last_reading), data_value: SensorArray(data_value), data_time: SensorArray(data_time), + min_value: SensorArray(min_value), + min_time: SensorArray(min_time), + max_value: SensorArray(max_value), + max_time: SensorArray(max_time), err_value: SensorArray(err_value), err_time: SensorArray(err_time), nerrors: SensorArray(nerrors), From 09ed4da80a28395913e133bcf98cd8c922ad8f64 Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Mon, 18 Dec 2023 00:47:09 -0800 Subject: [PATCH 2/5] fix sidecar --- app/sidecar/base.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sidecar/base.toml b/app/sidecar/base.toml index c7d1e256b..e9ce78840 100644 --- a/app/sidecar/base.toml +++ b/app/sidecar/base.toml @@ -180,7 +180,7 @@ task-slots = ["sys", "i2c_driver", "sprot"] name = "task-sensor" features = [] priority = 4 -max-sizes = {flash = 8192, ram = 4096 } +max-sizes = {flash = 8192, ram = 8192 } stacksize = 1024 start = true notifications = ["timer"] From 35927a6ca4b1495d91baf7213bd1555daae33b87 Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Mon, 18 Dec 2023 01:19:23 -0800 Subject: [PATCH 3/5] fix psc --- app/psc/base.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/psc/base.toml b/app/psc/base.toml index 530b3126b..ff901ac3c 100644 --- a/app/psc/base.toml +++ b/app/psc/base.toml @@ -215,7 +215,7 @@ notifications = ["timer"] [tasks.sensor] name = "task-sensor" priority = 3 -max-sizes = {flash = 8192, ram = 4096 } +max-sizes = {flash = 8192, ram = 8192 } stacksize = 1024 start = true notifications = ["timer"] From 47eb622e3a897f1f047add293ed2ded3276f53d2 Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Wed, 17 Jan 2024 10:40:10 -0800 Subject: [PATCH 4/5] fix #1592 --- drv/i2c-devices/src/max31790.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drv/i2c-devices/src/max31790.rs b/drv/i2c-devices/src/max31790.rs index 20463ebae..d3966e637 100644 --- a/drv/i2c-devices/src/max31790.rs +++ b/drv/i2c-devices/src/max31790.rs @@ -8,6 +8,7 @@ use crate::Validate; use bitfield::bitfield; use core::convert::TryFrom; use drv_i2c_api::*; +use ringbuf::*; use userlib::units::*; use userlib::*; @@ -250,6 +251,14 @@ fn write_reg16( device.write(&[register as u8, (val >> 8) as u8, (val & 0xff) as u8]) } +#[derive(Copy, Clone, PartialEq)] +enum Trace { + ZeroTach(Fan), + None, +} + +ringbuf!(Trace, 6, Trace::None); + impl Max31790 { pub fn new(device: &I2cDevice) -> Self { Self { device: *device } @@ -311,7 +320,18 @@ impl Max31790 { const NP: u32 = 2; const FREQ: u32 = 8192; - if count == TACH_POR_VALUE { + if count == 0 { + // + // We don't really expect this: generally, if a fan is off (or is + // otherwise emiting non-detectable tach input pulses), the + // controller will report the power-on-reset value for the tach + // count, not 0. So if we see a zero count, we will assume that + // this is an error rather than a 0 RPM reading, and record it to + // a (small) ring buffer and return accordingly. + // + ringbuf_entry!(Trace::ZeroTach(fan)); + Err(ResponseCode::BadDeviceState) + } else if count == TACH_POR_VALUE { Ok(Rpm(0)) } else { let rpm = (60 * FREQ * SR) / (count * NP); From 88f5c5817f37e212aaf8759488f4b9a950b9edf7 Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Wed, 17 Jan 2024 17:58:04 -0800 Subject: [PATCH 5/5] suggestion from Matt --- Cargo.lock | 1 + task/sensor/Cargo.toml | 1 + task/sensor/src/main.rs | 66 ++++++++++++++++++----------------------- 3 files changed, 31 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdfc9be66..96dc2d12c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4488,6 +4488,7 @@ dependencies = [ "idol-runtime", "mutable-statics", "num-traits", + "paste", "ringbuf", "serde", "task-sensor-api", diff --git a/task/sensor/Cargo.toml b/task/sensor/Cargo.toml index 1529e162c..9d3a43362 100644 --- a/task/sensor/Cargo.toml +++ b/task/sensor/Cargo.toml @@ -12,6 +12,7 @@ cortex-m.workspace = true hubpack.workspace = true idol-runtime.workspace = true num-traits.workspace = true +paste.workspace = true serde.workspace = true zerocopy.workspace = true diff --git a/task/sensor/src/main.rs b/task/sensor/src/main.rs index 60a95ccd8..2e7f7b652 100644 --- a/task/sensor/src/main.rs +++ b/task/sensor/src/main.rs @@ -289,43 +289,35 @@ fn main() -> ! { // sys_set_timer(Some(deadline), notifications::TIMER_MASK); - let ( - last_reading, - data_value, - data_time, - min_value, - min_time, - max_value, - max_time, - err_value, - err_time, - nerrors, - ) = mutable_statics::mutable_statics! { - static mut LAST_READING: [Option; NUM_SENSORS] = [|| None; _]; - static mut DATA_VALUE: [f32; NUM_SENSORS] = [|| f32::NAN; _]; - static mut DATA_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; - static mut MIN_VALUE: [f32; NUM_SENSORS] = [|| f32::MAX; _]; - static mut MIN_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; - static mut MAX_VALUE: [f32; NUM_SENSORS] = [|| f32::MIN; _]; - static mut MAX_TIME: [u64; NUM_SENSORS] = [|| 0u64; _]; - static mut ERR_VALUE: [NoData; NUM_SENSORS] = [|| NoData::DeviceUnavailable; _]; - static mut ERR_TIME: [u64; NUM_SENSORS] = [|| 0; _]; - static mut NERRORS: [u32; NUM_SENSORS] = [|| 0; _]; - }; - - let mut server = ServerImpl { - last_reading: SensorArray(last_reading), - data_value: SensorArray(data_value), - data_time: SensorArray(data_time), - min_value: SensorArray(min_value), - min_time: SensorArray(min_time), - max_value: SensorArray(max_value), - max_time: SensorArray(max_time), - err_value: SensorArray(err_value), - err_time: SensorArray(err_time), - nerrors: SensorArray(nerrors), - deadline, - }; + macro_rules! declare_server { + ($($name:ident: $t:ty = $n:expr;)*) => {{ + paste::paste! { + let ($($name),*) = mutable_statics::mutable_statics! { + $( + static mut [<$name:upper>]: [$t; NUM_SENSORS] = [|| $n; _]; + )* + }; + let ($($name),*) = ($(SensorArray($name)),*); + ServerImpl { + deadline, + $($name),* + } + }} + }; + } + + let mut server = declare_server!( + last_reading: Option = None; + data_value: f32 = f32::NAN; + data_time: u64 = 0u64; + min_value: f32 = f32::MAX; + min_time: u64 = 0u64; + max_value: f32 = f32::MIN; + max_time: u64 = 0u64; + err_value: NoData = NoData::DeviceUnavailable; + err_time: u64 = 0; + nerrors: u32 = 0; + ); let mut buffer = [0; idl::INCOMING_SIZE];