Skip to content

Commit

Permalink
Use new firmware.valid Command (#43)
Browse files Browse the repository at this point in the history
Make use of the new `firmware.valid` command to check if a firmware
image is valid before issuing the `firmware.update()` command.
  • Loading branch information
esarver authored Jan 28, 2025
1 parent 2da4105 commit d60ea55
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 29 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
Security -- in case of vulnerabilities.
-->

## [0.19.5]

### Changed

- Modify trebuchet firmware update procedure to use new command to check for validity

## [0.19.4]

### Fixed
Expand Down Expand Up @@ -141,7 +147,8 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
- Using `read_password` instead of `prompt_password` of rpassword crate (TSP-517)

<!--Version Comparison Links-->
[Unreleased]: https://github.com/tektronix/tsp-toolkit-kic-lib/compare/v0.19.4..HEAD
[Unreleased]: https://github.com/tektronix/tsp-toolkit-kic-lib/compare/v0.19.5..HEAD
[0.19.5]: https://github.com/tektronix/tsp-toolkit-kic-lib/releases/tag/v0.19.5
[0.19.4]: https://github.com/tektronix/tsp-toolkit-kic-lib/releases/tag/v0.19.4
[0.19.3]: https://github.com/tektronix/tsp-toolkit-kic-lib/releases/tag/v0.19.3
[0.19.2]: https://github.com/tektronix/tsp-toolkit-kic-lib/releases/tag/v0.19.2
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "tsp-toolkit-kic-lib"
description = "A library specifically enabling communication to the Keithley product-line of instruments"
version = "0.19.4"
version = "0.19.5"
authors = ["Keithley Instruments, LLC"]
edition = "2021"
repository = "https://github.com/tektronix/tsp-toolkit-kic-lib"
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ pub enum InstrumentError {
source: visa_rs::Error,
},

#[error("Instrument upgrade failed: {0}")]
FwUpgradeFailure(String),

/// An uncategorized error.
#[error("{0}")]
Other(String),
Expand Down
58 changes: 37 additions & 21 deletions src/instrument/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,13 @@ pub trait Instrument:
{
}

/// Read from a 'rw' until we are sure we have cleared the output queue.
///
/// # Warning
/// This functions calls a TSP command and therefore should not be used before
/// we know whether the instrument is in TSP mode (only applicable for TTI)
///
/// # Errors
/// Whatever can errors can occur with [`std::io::Read`], [`std::io::Write`] or
/// [`tsp_toolkit_kic_lib::interface::NonBlock`].
#[tracing::instrument(skip(rw))]
pub fn clear_output_queue<T: Read + Write + ?Sized>(
pub fn read_until<T: Read + Write + ?Sized>(
rw: &mut T,
one_of: Vec<String>,
max_attempts: usize,
delay_between_attempts: Duration,
) -> Result<()> {
let timestamp = chrono::Utc::now().to_string();

debug!("Sending print({timestamp})");
rw.write_all(format!("print(\"{timestamp}\")\n").as_bytes())?;

) -> Result<String> {
let mut accumulate = String::new();
for _ in 0..max_attempts {
std::thread::sleep(delay_between_attempts);
Expand All @@ -66,11 +53,40 @@ pub fn clear_output_queue<T: Read + Write + ?Sized>(
if !buf.is_empty() {
accumulate = format!("{accumulate}{}", String::from_utf8_lossy(buf));
}
if accumulate.contains(&timestamp) {
return Ok(());
for s in &one_of {
if accumulate.contains(s) {
return Ok(accumulate.trim().to_string());
}
}
}
Err(InstrumentError::Other(
"unable to clear instrument output queue".to_string(),
))
Err(InstrumentError::Other(String::default()))
}

/// Read from a 'rw' until we are sure we have cleared the output queue.
///
/// # Warning
/// This functions calls a TSP command and therefore should not be used before
/// we know whether the instrument is in TSP mode (only applicable for TTI)
///
/// # Errors
/// Whatever can errors can occur with [`std::io::Read`], [`std::io::Write`] or
/// [`tsp_toolkit_kic_lib::interface::NonBlock`].
#[tracing::instrument(skip(rw))]
pub fn clear_output_queue<T: Read + Write + ?Sized>(
rw: &mut T,
max_attempts: usize,
delay_between_attempts: Duration,
) -> Result<()> {
let timestamp = chrono::Utc::now().to_string();

debug!("Sending print({timestamp})");
rw.write_all(format!("print(\"{timestamp}\")\n").as_bytes())?;

match read_until(rw, vec![timestamp], max_attempts, delay_between_attempts) {
Ok(_) => Ok(()),
Err(InstrumentError::Other(_)) => Err(InstrumentError::Other(
"unable to clear instrument output queue".to_string(),
)),
Err(e) => Err(e),
}
}
37 changes: 32 additions & 5 deletions src/model/versatest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
authenticate::Authentication,
clear_output_queue,
info::{get_info, InstrumentInfo},
language, Info, Login, Reset, Script,
language, read_until, Info, Login, Reset, Script,
},
interface::NonBlock,
protocol::Protocol,
Expand Down Expand Up @@ -175,14 +175,41 @@ impl Flash for Instrument {
// back.
match clear_output_queue(self, 60 * 10, Duration::from_secs(1)) {
Ok(()) => {}
Err(InstrumentError::Other(_)) => return Err(InstrumentError::Other(
Err(InstrumentError::Other(_)) => return Err(InstrumentError::FwUpgradeFailure(
"Writing image took longer than 10 minutes. Check your connection and try again."
.to_string(),
)),
Err(e) => return Err(e),
}

//TODO CHECK ERRORS
self.write_all(b"if firmware.valid == nil or firmware.valid == true then print('VALID') else print('INVALID') end\n")?;
match read_until(
self,
vec!["VALID".to_string(), "INVALID".to_string()],
1000,
Duration::from_millis(1),
) {
Ok(s) if s == "VALID" => {
trace!("Firwmare was valid");
}
Ok(s) if s == "INVALID" => {
return Err(InstrumentError::FwUpgradeFailure(
"Unable to upgrade mainframe: Firmware was invalid".to_string(),
));
}
Ok(_) => {
trace!("Firmware validity superposition detected! 😱");
return Err(InstrumentError::FwUpgradeFailure(
"Upgrade status unknown: unable to read firmware validity".to_string(),
));
}
Err(InstrumentError::Other(s)) if s == String::default() => {
return Err(InstrumentError::FwUpgradeFailure(
"Upgrade status unknown: unable to read firmware validity".to_string(),
));
}
Err(e) => return Err(e),
}

if is_module {
self.write_all(format!("slot[{slot_number}].firmware.update()\n").as_bytes())?;
Expand All @@ -191,9 +218,9 @@ impl Flash for Instrument {
self.write_all(b"waitcomplete()\n")?;
self.write_all(format!("slot.start({slot_number})\n").as_bytes())?;
self.write_all(b"waitcomplete()\n")?;
match clear_output_queue(self, 60 * 5, Duration::from_secs(1)) {
match clear_output_queue(self, 60 * 10, Duration::from_secs(1)) {
Ok(()) => {}
Err(InstrumentError::Other(_)) => return Err(InstrumentError::Other(
Err(InstrumentError::Other(_)) => return Err(InstrumentError::FwUpgradeFailure(
"Upgrading module firmware took longer than 5 minutes. Check your hardware and try again."
.to_string(),
)),
Expand Down

0 comments on commit d60ea55

Please sign in to comment.