Fix UART timeout issues

1. Fix timeout detection for the verilator UART.
2. Add timeout detection for the common-case UART.
3. Print backtraces if available.

Signed-off-by: Chris Frantz <cfrantz@google.com>
diff --git a/sw/host/opentitanlib/Cargo.toml b/sw/host/opentitanlib/Cargo.toml
index b547ab2..ee522f2 100644
--- a/sw/host/opentitanlib/Cargo.toml
+++ b/sw/host/opentitanlib/Cargo.toml
@@ -9,7 +9,7 @@
 edition = "2018"
 
 [dependencies]
-anyhow = "1.0"
+anyhow = {version="1.0", features=["backtrace"]}
 thiserror = "1.0"
 lazy_static = "1.4.0"
 regex = "1"
diff --git a/sw/host/opentitanlib/src/transport/common/uart.rs b/sw/host/opentitanlib/src/transport/common/uart.rs
index 9bb2c51..a562e2b 100644
--- a/sw/host/opentitanlib/src/transport/common/uart.rs
+++ b/sw/host/opentitanlib/src/transport/common/uart.rs
@@ -4,6 +4,7 @@
 
 use serialport::SerialPort;
 use std::cell::RefCell;
+use std::io::ErrorKind;
 use std::time::Duration;
 
 use crate::io::uart::{Uart, UartError};
@@ -64,7 +65,11 @@
     fn read_timeout(&self, buf: &mut [u8], timeout: Duration) -> Result<usize> {
         let mut port = self.port.borrow_mut();
         port.set_timeout(timeout).wrap(UartError::ReadError)?;
-        let len = port.read(buf);
+        let result = port.read(buf);
+        let len = match result {
+            Err(ioerr) if ioerr.kind() == ErrorKind::TimedOut => Ok(0),
+            _ => result,
+        };
         port.set_timeout(Self::FOREVER).wrap(UartError::ReadError)?;
         Ok(len.wrap(UartError::ReadError)?)
     }
diff --git a/sw/host/opentitanlib/src/transport/verilator/uart.rs b/sw/host/opentitanlib/src/transport/verilator/uart.rs
index a85923a..1319435 100644
--- a/sw/host/opentitanlib/src/transport/verilator/uart.rs
+++ b/sw/host/opentitanlib/src/transport/verilator/uart.rs
@@ -52,7 +52,7 @@
                 // If we got a timeout from the uart, return 0 as per convention.
                 // Let all other errors propagate (wrapped in TransportError).
                 if let Some(ioerr) = e.downcast_ref::<io::Error>() {
-                    if ioerr.kind() != ErrorKind::TimedOut {
+                    if ioerr.kind() == ErrorKind::TimedOut {
                         return Ok(0);
                     }
                 }
diff --git a/sw/host/opentitantool/Cargo.toml b/sw/host/opentitantool/Cargo.toml
index 44f0b80..eafa9b9 100644
--- a/sw/host/opentitantool/Cargo.toml
+++ b/sw/host/opentitantool/Cargo.toml
@@ -13,7 +13,7 @@
 path = "src/main.rs"
 
 [dependencies]
-anyhow = "1.0"
+anyhow = {version="1.0", features=["backtrace"]}
 hex = "0.4"
 thiserror = "1.0"
 opentitanlib = {path="../opentitanlib"}
diff --git a/sw/host/opentitantool/src/main.rs b/sw/host/opentitantool/src/main.rs
index a72ca67..d19c6d7 100644
--- a/sw/host/opentitantool/src/main.rs
+++ b/sw/host/opentitantool/src/main.rs
@@ -4,6 +4,7 @@
 
 use anyhow::Result;
 use directories::ProjectDirs;
+use erased_serde::Serialize;
 use log::LevelFilter;
 use std::env::{args_os, ArgsOs};
 use std::ffi::OsString;
@@ -123,6 +124,22 @@
     Ok(opts)
 }
 
+// Print the result of a command.
+// If there is an error and `RUST_BACKTRACE=1` _and_ `--logging=debug`, print a backtrace.
+fn print_command_result(result: Result<Option<Box<dyn Serialize>>>) -> Result<()> {
+    match result {
+        Ok(Some(value)) => {
+            println!("{}", serde_json::to_string_pretty(&value)?);
+            Ok(())
+        }
+        Ok(None) => Ok(()),
+        Err(e) => {
+            log::debug!("{:?}", e);
+            Err(e)
+        }
+    }
+}
+
 // Execute is a convenience function for taking a list of strings,
 // parsing them into a command, executing the command and printing the result.
 fn execute<I>(args: I, opts: &Opts, transport: &TransportWrapper) -> Result<()>
@@ -132,9 +149,7 @@
     let command = RootCommandHierarchy::from_iter(
         std::iter::once(OsString::from("opentitantool")).chain(args),
     );
-    if let Some(value) = command.run(opts, transport)? {
-        println!("{}", serde_json::to_string_pretty(&value)?);
-    }
+    print_command_result(command.run(opts, &transport))?;
     Ok(())
 }
 
@@ -150,9 +165,6 @@
             &transport,
         )?;
     }
-
-    if let Some(value) = opts.command.run(&opts, &transport)? {
-        println!("{}", serde_json::to_string_pretty(&value)?);
-    }
+    print_command_result(opts.command.run(&opts, &transport))?;
     Ok(())
 }