Skip to content

Commit

Permalink
[opentitanlib] split Jtag into JtagChain and Jtag
Browse files Browse the repository at this point in the history
`JtagChain` is now the intermediate type where the adapter has been
configured but the specific tap has not yet been selected. This serves
as the type-state for the previous unconnected `Jtag`, and the new
`Jtag` is the type-state for a connected `Jtag`.

Signed-off-by: Gary Guo <[email protected]>
  • Loading branch information
nbdd0121 authored and jwnrt committed Nov 15, 2023
1 parent 405fcdd commit 3860cdd
Show file tree
Hide file tree
Showing 25 changed files with 281 additions and 212 deletions.
6 changes: 3 additions & 3 deletions sw/host/opentitanlib/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::io::emu::Emulator;
use crate::io::gpio::{GpioMonitoring, GpioPin, PinMode, PullMode};
use crate::io::i2c::Bus;
use crate::io::ioexpander::IoExpander;
use crate::io::jtag::{Jtag, JtagParams};
use crate::io::jtag::{JtagChain, JtagParams};
use crate::io::nonblocking_help::NonblockingHelp;
use crate::io::spi::{Target, TransferMode};
use crate::io::uart::Uart;
Expand Down Expand Up @@ -663,8 +663,8 @@ impl TransportWrapper {
})
}

/// Returns a [`Jtag`] implementation.
pub fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn Jtag + '_>> {
/// Returns a [`JtagChain`] implementation.
pub fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
self.transport.jtag(opts)
}

Expand Down
18 changes: 12 additions & 6 deletions sw/host/opentitanlib/src/io/jtag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct JtagParams {
}

impl JtagParams {
pub fn create<'t>(&self, transport: &'t TransportWrapper) -> Result<Box<dyn Jtag + 't>> {
pub fn create<'t>(&self, transport: &'t TransportWrapper) -> Result<Box<dyn JtagChain + 't>> {
let jtag = transport.jtag(self)?;
Ok(jtag)
}
Expand All @@ -46,15 +46,21 @@ pub enum JtagError {
impl_serializable_error!(JtagError);

/// A trait which represents a JTAG interface.
///
/// JTAG lines form a daisy-chained topology and can connect multiple TAPs together in a chain.
/// This trait represents an adaptor that has been configured to connect to a given JTAG chain,
/// but have not yet been configured to only access a particular TAP.
pub trait JtagChain {
/// Connect to the given JTAG TAP on this chain.
fn connect(self: Box<Self>, tap: JtagTap) -> Result<Box<dyn Jtag>>;
}

/// A trait which represents a TAP on a JTAG chain.
pub trait Jtag {
/// Connect to the given JTAG TAP.
fn connect(&mut self, tap: JtagTap) -> Result<()>;
/// Disconnect from the TAP.
fn disconnect(self: Box<Self>) -> Result<()>;
/// Get TAP we are currently connected too.
fn tap(&self) -> Option<JtagTap>;

// Commands
fn tap(&self) -> JtagTap;

/// Read a lifecycle controller register.
fn read_lc_ctrl_reg(&mut self, reg: &LcCtrlReg) -> Result<u32>;
Expand Down
19 changes: 12 additions & 7 deletions sw/host/opentitanlib/src/test_utils/lc_transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,11 @@ fn setup_lc_transition(
/// transport.reset_target(init.bootstrap.options.reset_delay, true).unwrap();
///
/// // Connect to the LC controller TAP.
/// let mut jtag = transport.jtag(jtag_opts).unwrap();
/// jtag.connect(JtagTap::LcTap).expect("failed to connect to LC TAP");
/// let mut jtag = transport
/// .jtag(jtag_opts)
/// .unwrap()
/// .connect(JtagTap::LcTap)
/// .expect("failed to connect to LC TAP");
///
/// let test_exit_token = DifLcCtrlToken::from([0xff; 16]);
///
Expand All @@ -143,8 +146,11 @@ fn setup_lc_transition(
/// Some(JtagTap::LcTap),
/// ).expect("failed to trigger transition to prod");
///
/// jtag = transport.jtag(jtag_opts).unwrap();
/// jtag.connect(JtagTap::LcTap).expect("failed to reconnect to LC TAP");
/// jtag = transport
/// .jtag(jtag_opts)
/// .unwrap()
/// .connect(JtagTap::LcTap)
/// .expect("failed to reconnect to LC TAP");
///
/// assert_eq!(
/// jtag.read_lc_ctrl_reg(&LcCtrlReg::LCState).unwrap(),
Expand Down Expand Up @@ -249,8 +255,7 @@ pub fn trigger_volatile_raw_unlock<'t>(
// because a volatile unlock will trigger a TAP strap resampling immediately upon success.
if post_transition_tap == JtagTap::RiscvTap {
jtag.disconnect()?;
jtag = transport.jtag(jtag_params)?;
jtag.connect(JtagTap::RiscvTap)?;
jtag = transport.jtag(jtag_params)?.connect(JtagTap::RiscvTap)?;
}

wait_for_status(
Expand All @@ -264,7 +269,7 @@ pub fn trigger_volatile_raw_unlock<'t>(
}

pub fn wait_for_status(jtag: &mut dyn Jtag, timeout: Duration, status: LcCtrlStatus) -> Result<()> {
let jtag_tap = jtag.tap().unwrap();
let jtag_tap = jtag.tap();

// Wait for LC controller to be ready.
poll::poll_until(timeout, Duration::from_millis(50), || {
Expand Down
6 changes: 3 additions & 3 deletions sw/host/opentitanlib/src/transport/chip_whisperer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::path::PathBuf;
use std::rc::Rc;

use crate::io::gpio::GpioPin;
use crate::io::jtag::{Jtag, JtagParams};
use crate::io::jtag::{JtagChain, JtagParams};
use crate::io::spi::Target;
use crate::io::uart::{Uart, UartError};
use crate::transport::common::fpga::{ClearBitstream, FpgaProgram};
Expand Down Expand Up @@ -181,9 +181,9 @@ impl<B: Board + 'static> Transport for ChipWhisperer<B> {
}
}

fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn Jtag + '_>> {
fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
Ok(Box::new(OpenOcdJtagChain::new(
match self.openocd_adapter_config {
&match self.openocd_adapter_config {
Some(ref path) => std::fs::read_to_string(path)?,
None => String::new(),
},
Expand Down
8 changes: 4 additions & 4 deletions sw/host/opentitanlib/src/transport/hyperdebug/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::rc::Rc;

use crate::io::gpio::{GpioMonitoring, GpioPin};
use crate::io::i2c::Bus;
use crate::io::jtag::{Jtag, JtagParams};
use crate::io::jtag::{JtagChain, JtagParams};
use crate::io::spi::Target;
use crate::io::uart::Uart;
use crate::transport::chip_whisperer::board::Board;
Expand Down Expand Up @@ -623,16 +623,16 @@ impl<T: Flavor> Transport for Hyperdebug<T> {
}
}

fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn Jtag + '_>> {
fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
ensure!(
self.cmsis_interface.is_some(),
TransportError::InvalidInterface(TransportInterfaceType::Jtag),
);
// Tell OpenOCD to use its CMSIS-DAP driver, and to connect to the same exact USB
// HyperDebug device that we are.
let usb_device = self.inner.usb_device.borrow();
let new_jtag: Box<dyn Jtag> = Box::new(OpenOcdJtagChain::new(
format!(
let new_jtag = Box::new(OpenOcdJtagChain::new(
&format!(
"{}; cmsis_dap_vid_pid 0x{:04x} 0x{:04x}; adapter serial \"{}\";",
include_str!(env!("openocd_cmsis_dap_adapter_cfg")),
usb_device.get_vendor_id(),
Expand Down
6 changes: 3 additions & 3 deletions sw/host/opentitanlib/src/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::bootstrap::BootstrapOptions;
use crate::io::emu::Emulator;
use crate::io::gpio::{GpioMonitoring, GpioPin};
use crate::io::i2c::Bus;
use crate::io::jtag::{Jtag, JtagParams};
use crate::io::jtag::{JtagChain, JtagParams};
use crate::io::nonblocking_help::{NoNonblockingHelp, NonblockingHelp};
use crate::io::spi::Target;
use crate::io::uart::Uart;
Expand Down Expand Up @@ -111,8 +111,8 @@ pub trait Transport {
Ok(())
}

/// Returns a [`Jtag`] implementation.
fn jtag(&self, _opts: &JtagParams) -> Result<Box<dyn Jtag + '_>> {
/// Returns a [`JtagChain`] implementation.
fn jtag(&self, _opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
Err(TransportError::InvalidInterface(TransportInterfaceType::Jtag).into())
}
/// Returns a SPI [`Target`] implementation.
Expand Down
Loading

0 comments on commit 3860cdd

Please sign in to comment.