Skip to content

Commit

Permalink
[opentitantool] Allow changing of JTAG pins
Browse files Browse the repository at this point in the history
HyperDebug by default does JTAG on five particular pins.  However, as it
is all bit-banging with no true hardware support, it is able to use
almost any combination of pins.

This PR introduces a transport-specific command to "move" the JTAG
functionality to a different set of pins.

Usage:
`opentitantool --interface=hyperdebug transport set-jtag-pins <TCLK> <TMS> <TDI> <TDO> <TRSTn>`

Signed-off-by: Jes B. Klinke <[email protected]>

Change-Id: Ibf61be39949b6330f4dd1ec01c44bbdc5cc2350c
  • Loading branch information
jesultra committed Jan 23, 2024
1 parent ea0b302 commit 86143ec
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
29 changes: 28 additions & 1 deletion sw/host/opentitanlib/src/transport/hyperdebug/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use crate::transport::chip_whisperer::ChipWhisperer;
use crate::transport::common::fpga::{ClearBitstream, FpgaProgram};
use crate::transport::common::uart::{flock_serial, SerialPortExclusiveLock, SerialPortUart};
use crate::transport::{
Capabilities, Capability, Transport, TransportError, TransportInterfaceType, UpdateFirmware,
Capabilities, Capability, SetJtagPins, Transport, TransportError, TransportInterfaceType,
UpdateFirmware,
};
use crate::util::openocd::OpenOcdJtagChain;
use crate::util::usb::UsbBackend;
Expand Down Expand Up @@ -632,6 +633,32 @@ impl<T: Flavor> Transport for Hyperdebug<T> {
update_firmware_action.progress.as_ref(),
update_firmware_action.force,
)
} else if let Some(jtag_set_pins) = action.downcast_ref::<SetJtagPins>() {
match (
&jtag_set_pins.tclk,
&jtag_set_pins.tms,
&jtag_set_pins.tdi,
&jtag_set_pins.tdo,
&jtag_set_pins.trst,
) {
(Some(tclk), Some(tms), Some(tdi), Some(tdo), Some(trst)) => {
self.inner.cmd_no_output(&format!(
"jtag set-pins {} {} {} {} {}",
tclk.get_internal_pin_name()
.ok_or(TransportError::InvalidOperation)?,
tms.get_internal_pin_name()
.ok_or(TransportError::InvalidOperation)?,
tdi.get_internal_pin_name()
.ok_or(TransportError::InvalidOperation)?,
tdo.get_internal_pin_name()
.ok_or(TransportError::InvalidOperation)?,
trst.get_internal_pin_name()
.ok_or(TransportError::InvalidOperation)?,
))?;
Ok(None)
}
_ => Err(TransportError::UnsupportedOperation.into()),
}
} else if let Some(fpga_program) = action.downcast_ref::<FpgaProgram>() {
T::load_bitstream(fpga_program).map(|_| None)
} else if let Some(clear) = action.downcast_ref::<ClearBitstream>() {
Expand Down
9 changes: 9 additions & 0 deletions sw/host/opentitanlib/src/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ pub struct Bootstrap {
pub image_path: PathBuf,
}

/// Some transports allow dynamically changing which pins are used for JTAG.
pub struct SetJtagPins {
pub tclk: Option<Rc<dyn GpioPin>>,
pub tms: Option<Rc<dyn GpioPin>>,
pub tdi: Option<Rc<dyn GpioPin>>,
pub tdo: Option<Rc<dyn GpioPin>>,
pub trst: Option<Rc<dyn GpioPin>>,
}

pub trait ProgressIndicator {
// Begins a new stage, indicating "size" of this stage in bytes. `name` can be the empty
// string, for instance if the operation has only a single stage.
Expand Down
37 changes: 37 additions & 0 deletions sw/host/opentitantool/src/command/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use std::time::Duration;

use opentitanlib::app::command::CommandDispatch;
use opentitanlib::app::{StagedProgressBar, TransportWrapper};
use opentitanlib::io::jtag::JtagParams;
use opentitanlib::transport::verilator::transport::Watch;
use opentitanlib::transport::Capability;
use opentitanlib::transport::SetJtagPins;
use opentitanlib::transport::UpdateFirmware;

/// Initialize state of a transport debugger device to fit the device under test. This
Expand All @@ -41,6 +44,39 @@ impl CommandDispatch for TransportInit {
}
}

#[derive(Debug, Args)]
pub struct TransportSetJtagPins {
#[command(flatten)]
pub jtag_params: JtagParams,

pub tclk: String,
pub tms: String,
pub tdi: String,
pub tdo: String,
pub trst: String,
}

impl CommandDispatch for TransportSetJtagPins {
fn run(
&self,
_context: &dyn Any,
transport: &TransportWrapper,
) -> Result<Option<Box<dyn Annotate>>> {
transport
.capabilities()?
.request(Capability::GPIO | Capability::JTAG)
.ok()?;

transport.dispatch(&SetJtagPins {
tclk: Some(transport.gpio_pin(&self.tclk)?),
tms: Some(transport.gpio_pin(&self.tms)?),
tdi: Some(transport.gpio_pin(&self.tdi)?),
tdo: Some(transport.gpio_pin(&self.tdo)?),
trst: Some(transport.gpio_pin(&self.trst)?),
})
}
}

/// Updates the firmware of the debugger/transport. If no argument is given, a suitable
/// "official" firmware will be used, if one such was compiled into the OpenTitanTool binary. For
/// instructions on how to build HyperDebug firmware locally, see
Expand Down Expand Up @@ -144,6 +180,7 @@ impl CommandDispatch for TransportQueryAll {
#[derive(Debug, Subcommand, CommandDispatch)]
pub enum TransportCommand {
Init(TransportInit),
SetJtagPins(TransportSetJtagPins),
VerilatorWatch(VerilatorWatch),
UpdateFirmware(TransportUpdateFirmware),
Query(TransportQuery),
Expand Down

0 comments on commit 86143ec

Please sign in to comment.