From 8d23171946e768bcd624972dc58f5bc7b51419d7 Mon Sep 17 00:00:00 2001 From: cam Date: Fri, 16 Feb 2024 17:28:39 +1300 Subject: [PATCH 1/5] Program RP2040 firmware with if old firmware or not connecting successfully --- _releases/scripts/postinst | 4 +-- _releases/tc2-agent.service | 2 +- src/main.rs | 49 +++++++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/_releases/scripts/postinst b/_releases/scripts/postinst index faeaa66..a83035a 100644 --- a/_releases/scripts/postinst +++ b/_releases/scripts/postinst @@ -1,6 +1,4 @@ #!/bin/bash systemctl daemon-reload systemctl enable tc2-agent.service -systemctl stop tc2-agent.service -tc2-hat-rp2040 --elf /etc/cacophony/rp2040-firmware.elf -systemctl start tc2-agent.service +systemctl restart tc2-agent.service diff --git a/_releases/tc2-agent.service b/_releases/tc2-agent.service index fef5fbc..9954be9 100644 --- a/_releases/tc2-agent.service +++ b/_releases/tc2-agent.service @@ -6,7 +6,7 @@ After=multi-user.target [Service] Type=simple ExecStart=/usr/bin/tc2-agent -Restart=on-failure +Restart=always RestartSec=5s # Give real-time priority diff --git a/src/main.rs b/src/main.rs index 97de11d..37d82cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,9 @@ use std::time::Instant; use std::{thread, time::Duration}; use thread_priority::ThreadBuilderExt; use thread_priority::*; +use std::process::Command; +use std::io; +use std::process; use crate::cptv_header::{decode_cptv_header_streaming, CptvHeader}; use crate::device_config::DeviceConfig; @@ -441,27 +444,18 @@ fn main() { ms_elapsed = 0; }, _ => { - const NUM_ATTEMPTS_BEFORE_RESET: usize = 10; + const NUM_ATTEMPTS_BEFORE_REPROGRAM: usize = 20; ms_elapsed += recv_timeout_ms; - if ms_elapsed > 5000 { + if ms_elapsed > 10000 { ms_elapsed = 0; reconnects += 1; - if reconnects == NUM_ATTEMPTS_BEFORE_RESET { - let date = chrono::Local::now(); - warn!("Resetting rp2040 at {}", date.format("%Y-%m-%d--%H:%M:%S")); - reconnects = 0; - prev_frame_num = None; - - if !run_pin.is_set_high() { - run_pin.set_high(); - sleep(Duration::from_millis(1000)); + if reconnects == NUM_ATTEMPTS_BEFORE_REPROGRAM { + let e = program_rp2040(); + if e.is_err() { + warn!("Failed to reprogram RP2040: {}", e.unwrap_err()); } - - run_pin.set_low(); - sleep(Duration::from_millis(1000)); - run_pin.set_high(); } else { - info!("-- #{reconnects} waiting for frames from rp2040 (resetting rp2040 after {} more attempts)", NUM_ATTEMPTS_BEFORE_RESET - reconnects); + info!("-- #{reconnects} waiting to connect to rp2040 (reprogram RP2040 after {} more attempts)", NUM_ATTEMPTS_BEFORE_REPROGRAM - reconnects); } } } @@ -675,8 +669,13 @@ fn main() { info!("Got startup info: radiometry enabled: {}, firmware version: {}, lepton serial #{}", radiometry_enabled, firmware_version, lepton_serial_number); if firmware_version != EXPECTED_RP2040_FIRMWARE_VERSION { exit_cleanly(&mut attiny_i2c_interface); - error!("Unsupported firmware version, expected {}, got {}", EXPECTED_RP2040_FIRMWARE_VERSION, firmware_version); - panic!("Exit"); + info!("Unsupported firmware version, expected {}, got {}. Will reprogram RP2040.", EXPECTED_RP2040_FIRMWARE_VERSION, firmware_version); + let e = program_rp2040(); + if e.is_err() { + warn!("Failed to reprogram rp2040: {}", e.unwrap_err()); + panic!("Exit"); + } + process::exit(0); } if device_config.use_low_power_mode() && !radiometry_enabled { exit_cleanly(&mut attiny_i2c_interface); @@ -868,6 +867,20 @@ pub const CRC_AUG_CCITT: Algorithm = Algorithm { residue: 0x0000, }; +fn program_rp2040() -> io::Result<()> { + let status = Command::new("tc2-hat-rp2040") + .arg("--elf") + .arg("/etc/cacophony/rp2040-firmware.elf") + .status()?; + + if !status.success() { + return Err(io::Error::new(io::ErrorKind::Other, "Command execution failed")); + } + + println!("Updated RP2040 firmware."); + Ok(()) +} + fn write_attiny_command(attiny_i2c: &mut I2c, command: u8, value: u8) -> Result<(), &'static str> { let mut payload = [command, value, 0x00, 0x00]; let crc = Crc::::new(&CRC_AUG_CCITT).checksum(&payload[0..=1]); From 66a4e2599844202a09dea232ac81fda097e9a947 Mon Sep 17 00:00:00 2001 From: cam Date: Mon, 19 Feb 2024 15:22:14 +1300 Subject: [PATCH 2/5] Update dist to focal (Ubuntu 20.04 LTS) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fbd4500..067ae13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ rust: - stable os: linux -dist: bionic +dist: focal addons: apt: From a49d4e7ccdbde6e40447e08e9a3e7087a4779ea7 Mon Sep 17 00:00:00 2001 From: cam Date: Fri, 23 Feb 2024 19:19:14 +1300 Subject: [PATCH 3/5] Make revision blank, default is 1 --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 3dc61fa..b6a262f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,3 +47,4 @@ assets = [ ["_releases/tc2-firmware", "/etc/cacophony/rp2040-firmware.elf", "664"], ] maintainer-scripts = "_releases/scripts" +revision = "" From cff2e6ea704f35c466126044c8e5e57b5c0d8978 Mon Sep 17 00:00:00 2001 From: cam Date: Wed, 6 Mar 2024 23:22:48 +1300 Subject: [PATCH 4/5] Update firmware --- .travis.yml | 2 +- src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 067ae13..f0cc8f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: - if [ -n "$TRAVIS_TAG" ]; then sed -i "s/version = \"0.0.0-snapshot\"/version = \"${TRAVIS_TAG#v}\"/g" Cargo.toml; fi - cargo install cargo-deb - cargo build --release --target=armv7-unknown-linux-musleabihf - - wget -O _releases/tc2-firmware https://github.com/TheCacophonyProject/tc2-firmware/releases/download/v0.1.2/tc2-firmware + - wget -O _releases/tc2-firmware https://github.com/TheCacophonyProject/tc2-firmware/releases/download/v0.1.3/tc2-firmware - cargo deb --target=armv7-unknown-linux-musleabihf --output tc2-agent_${TRAVIS_TAG#v}_armhf.deb deploy: diff --git a/src/main.rs b/src/main.rs index 37d82cc..05693b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ use rustbus::connection::Timeout; use rustbus::{get_system_bus_path, DuplexConn}; use simplelog::*; -const EXPECTED_RP2040_FIRMWARE_VERSION: u32 = 9; +const EXPECTED_RP2040_FIRMWARE_VERSION: u32 = 10; const EXPECTED_ATTINY_FIRMWARE_VERSION: u8 = 12; const SEGMENT_LENGTH: usize = 9760; const FRAME_LENGTH: usize = SEGMENT_LENGTH * 4; From 57567520b702e84c93fcc17872eb1f0bddc793a9 Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 11 Mar 2024 09:20:28 +1300 Subject: [PATCH 5/5] v10: - Make sure we can reset the rp2040 from tc2-agent a *second* time. --- src/main.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 05693b3..add5aa1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,8 +16,11 @@ use rppal::{ spi::{Bus, Mode, Polarity, SlaveSelect, Spi}, }; use std::fs; +use std::io; use std::ops::Not; use std::path::Path; +use std::process; +use std::process::Command; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{channel, TryRecvError}; use std::sync::Arc; @@ -26,9 +29,6 @@ use std::time::Instant; use std::{thread, time::Duration}; use thread_priority::ThreadBuilderExt; use thread_priority::*; -use std::process::Command; -use std::io; -use std::process; use crate::cptv_header::{decode_cptv_header_streaming, CptvHeader}; use crate::device_config::DeviceConfig; @@ -341,6 +341,8 @@ fn main() { pin.set_interrupt(Trigger::RisingEdge).expect("Unable to set pi ping interrupt"); let (tx, rx) = channel(); let (restart_tx, restart_rx) = channel(); + let cross_thread_signal = Arc::new(AtomicBool::new(false)); + let cross_thread_signal_2 = cross_thread_signal.clone(); let _ = thread::Builder::new().name("frame-socket".to_string()).spawn_with_priority(ThreadPriority::Max, move |result| { // Spawn a thread which can output the frames, converted to rgb grayscale @@ -350,10 +352,10 @@ fn main() { info!("Connecting to frame socket {}", address); let mut reconnects = 0; let mut prev_frame_num = None; - loop { info!("Entering frame-socket loop"); if let Ok(_) = restart_rx.try_recv() { + cross_thread_signal_2.store(true, Ordering::Relaxed); info!("Restarting rp2040"); if !run_pin.is_set_high() { run_pin.set_high(); @@ -372,6 +374,7 @@ fn main() { 'send_loop: loop { // Check if we need to reset rp2040 because of a config change if let Ok(_) = restart_rx.try_recv() { + cross_thread_signal_2.store(true, Ordering::Relaxed); loop { info!("Restarting rp2040"); if !run_pin.is_set_high() { @@ -840,6 +843,10 @@ fn main() { sent_reset_request = true; let _ = restart_tx.send(true); } + if cross_thread_signal.load(Ordering::Relaxed) { + sent_reset_request = false; + cross_thread_signal.store(false, Ordering::Relaxed); + } } FRAME_BUFFER.swap(); let _ = tx.send((Some((radiometry_enabled, is_recording, firmware_version, lepton_serial_number.clone())), None)); @@ -874,7 +881,10 @@ fn program_rp2040() -> io::Result<()> { .status()?; if !status.success() { - return Err(io::Error::new(io::ErrorKind::Other, "Command execution failed")); + return Err(io::Error::new( + io::ErrorKind::Other, + "Command execution failed", + )); } println!("Updated RP2040 firmware.");