Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[opentitantool] Allow changing which pins to use for JTAG #20934

Merged
merged 1 commit into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading