From e63eed4c4ec6fe47356d3e018a1e33940ea8618f Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Thu, 11 Jul 2024 13:27:03 +0200
Subject: [PATCH] Ignore malformed messages

---
 controller/src/logic.rs | 12 ++++++------
 i2c2-target/src/lib.rs  | 24 +++++++++++++++++++++---
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/controller/src/logic.rs b/controller/src/logic.rs
index e07c838..10b40e8 100644
--- a/controller/src/logic.rs
+++ b/controller/src/logic.rs
@@ -57,7 +57,7 @@ fn handle_command(command: &[u8], response: &mut Deque<u8, MESSAGE_SIZE>) {
         [WHO_AM_I, ..] => {
             let _ = response.push_back(0x57);
         }
-        &[MAX_MOTOR_PERCENTAGE, p, ..] => {
+        &[MAX_MOTOR_PERCENTAGE, p] => {
             if (1..=100).contains(&p) {
                 state.max_motor_percentage = p;
             } else {
@@ -67,7 +67,7 @@ fn handle_command(command: &[u8], response: &mut Deque<u8, MESSAGE_SIZE>) {
         [MAX_MOTOR_PERCENTAGE] => {
             let _ = response.push_back(state.max_motor_percentage);
         }
-        [MOTOR_SPEED, ms @ ..] if ms.len() >= 2 => {
+        [MOTOR_SPEED, ms @ ..] if ms.len() == 2 => {
             let (max_pwm, mmp) = (
                 state.motors.max_pwm() as i32,
                 i32::from(state.max_motor_percentage),
@@ -93,12 +93,12 @@ fn handle_command(command: &[u8], response: &mut Deque<u8, MESSAGE_SIZE>) {
                 }
             }
         }
-        [MOTOR_SPEED, ..] => {
+        [MOTOR_SPEED] => {
             for &s in &state.motor_speed {
                 let _ = response.push_back(s);
             }
         }
-        [ENCODER_TICKS, ..] => {
+        [ENCODER_TICKS] => {
             let (left, right) = state.encoders.ticks();
             let (left, right) = (left.to_le_bytes(), right.to_le_bytes());
             let _ = response.push_back(left[0]);
@@ -106,8 +106,8 @@ fn handle_command(command: &[u8], response: &mut Deque<u8, MESSAGE_SIZE>) {
             let _ = response.push_back(right[0]);
             let _ = response.push_back(right[1]);
         }
-        &[idx, ..] => {
-            defmt::warn!("unknown register {:#04x}", idx);
+        &[_, ..] => {
+            defmt::warn!("unknown command or args {:#04x}", command);
         }
         &[] => {
             defmt::warn!("received empty command");
diff --git a/i2c2-target/src/lib.rs b/i2c2-target/src/lib.rs
index 2ab0bb3..1d33e99 100644
--- a/i2c2-target/src/lib.rs
+++ b/i2c2-target/src/lib.rs
@@ -110,9 +110,15 @@ impl I2C2 {
         let af_num = SclPin::af_num(&pb10);
         assert_eq!(af_num, SdaPin::af_num(&pb11));
         let mut pb10 = Flex::new(pb10);
-        pb10.set_as_af_unchecked(af_num, AfType::output(OutputType::OpenDrain, Speed::Low));
+        pb10.set_as_af_unchecked(
+            af_num,
+            AfType::output(OutputType::OpenDrain, Speed::VeryHigh),
+        );
         let mut pb11 = Flex::new(pb11);
-        pb11.set_as_af_unchecked(af_num, AfType::output(OutputType::OpenDrain, Speed::Low));
+        pb11.set_as_af_unchecked(
+            af_num,
+            AfType::output(OutputType::OpenDrain, Speed::VeryHigh),
+        );
 
         // Turn I2C2 clock on
         pac::RCC.apb1enr().modify(|w| w.set_i2c2en(true));
@@ -131,6 +137,7 @@ impl I2C2 {
         // Enable I2C2
         pac::I2C2.cr1().write(|w| {
             w.set_pe(true);
+            w.set_nostretch(false);
         });
         // Set ack generation
         pac::I2C2.cr1().modify(|w| {
@@ -162,11 +169,19 @@ unsafe fn I2C2_EV() {
         pac::I2C2.cr1().read().0,
         pac::I2C2.cr2().read().0
     );
+    if sr1.ovr() {
+        defmt::error!("overrun detected");
+        pac::I2C2.sr1().modify(|w| w.set_ovr(false));
+    }
     let state = unsafe { STATE.as_mut().unwrap() };
     if sr1.rxne() {
         defmt::trace!("I2C2_EV RXNE");
         let b = pac::I2C2.dr().read().0 as u8;
-        defmt::trace!("received byte {:#04x}", &b);
+        defmt::trace!(
+            "received byte {:#04x} - sr1 is now {:#06x}",
+            &b,
+            pac::I2C2.sr1().read().0
+        );
         if state.incoming.push(b).is_err() {
             defmt::error!("I2C byte has overfilled the buffer");
         }
@@ -215,5 +230,8 @@ unsafe fn I2C2_EV() {
         } else {
             state.set_write_in_progress();
         }
+        // Read DR to avoid overrun
+        pac::I2C2.dr().read();
+        defmt::trace!("sr1 is now {:#06x}", pac::I2C2.sr1().read().0);
     }
 }
-- 
GitLab