From 490b1c9aad062a5a1d41a71f1a08086ea23e107b Mon Sep 17 00:00:00 2001
From: Benjamin Koch <bbbsnowball@gmail.com>
Date: Tue, 30 May 2023 01:53:10 +0200
Subject: [PATCH] add reset via Modbus

---
 firmware/rust1/rtumaster_pymodbus.py |  4 ++++
 firmware/rust1/src/bin/heizung.rs    | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/firmware/rust1/rtumaster_pymodbus.py b/firmware/rust1/rtumaster_pymodbus.py
index a5cb29d..08b36a4 100644
--- a/firmware/rust1/rtumaster_pymodbus.py
+++ b/firmware/rust1/rtumaster_pymodbus.py
@@ -54,6 +54,10 @@ def main():
             write_registers=[struct.unpack(">H", b"PI")[0], 103], slave=DEVICE_ADDR)
         logger.info("read/write regs: %s: %r", x, x.registers)
 
+        if False:
+            x = client.write_registers(1, struct.unpack(">H", b"RE")[0], slave=DEVICE_ADDR)
+            logger.info("write to reset: %s", x)
+
         x = client.read_file_record([
             # documentation says tuple of: Reference type, File number, Record Number, Record Length
             # but actually an object is expected:
diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs
index ef40a5a..d9bd06f 100644
--- a/firmware/rust1/src/bin/heizung.rs
+++ b/firmware/rust1/src/bin/heizung.rs
@@ -306,6 +306,13 @@ async fn adc_task(shared_data: &'static AdcData, adc: ADC, mut en_measure_curren
 }
 
 
+#[embassy_executor::task]
+async fn reset_soon(delay: Duration) {
+    Timer::after(delay).await;
+    cortex_m::peripheral::SCB::sys_reset();
+}
+
+
 const FLASH_SIZE: usize = 2 * 1024 * 1024;
 
 #[derive(Clone, Copy, PartialEq, Eq)]
@@ -334,6 +341,8 @@ struct ModBusRegs<'a> {
     consistent_read_addr: u16,
     consistent_read_length: u16,
     consistent_read_data: [u16; 4],
+
+    spawner: Spawner,
 }
 
 impl<'a> ModBusRegs<'a> {
@@ -471,6 +480,7 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> {
                 const OK: u16 = be("OK");  // mark booted
                 const UP: u16 = be("UP");  // mark updated -> swap to DFU on next reset
                 const PI: u16 = be("PI");  // ping / no-op
+                const RE: u16 = be("RE");  // reset
                 match value {
                     OK => {
                         self.uf2updater.mark_booted().map(|_| value)
@@ -484,6 +494,15 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> {
                     PI => {
                         Ok(value)
                     },
+                    RE => {
+                        match self.spawner.spawn(reset_soon(Duration::from_millis(100))) {
+                            Ok(()) => Ok(value),
+                            Err(err) => {
+                                error!("Couldn't spawn reset_soon: {:?}", err);
+                                Err(ModbusErrorCode::ServerDeviceFailure)
+                            }
+                        }
+                    },
                     _ => Err(ModbusErrorCode::IllegalDataValue),
                 }
             },
@@ -649,6 +668,7 @@ async fn main2(spawner: Spawner) {
             consistent_read_addr: u16::default(),
             consistent_read_length: u16::default(),
             consistent_read_data: [0; 4],
+            spawner: spawner.clone(),
         }),
     );
     unwrap!(spawner.spawn(uart_task(rs485)));
-- 
GitLab