use bitvec::{order::Lsb0, vec::BitVec};
use crate::{
Error,
ErrorKind::BrokenChain,
jtag::Register::{Data, Instruction},
};
#[cfg(feature = "backend-jtag-taps")]
mod jtag_taps;
#[cfg(feature = "backend-jtag-taps")]
pub use ::jtag_taps::statemachine::{JtagState, Register};
#[cfg(not(feature = "backend-jtag-taps"))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Register {
Data,
Instruction,
}
#[cfg(not(feature = "backend-jtag-taps"))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum JtagState {
Reset = 0,
Idle = 1,
SelectDR = 2,
CaptureDR = 3,
ShiftDR = 4,
Exit1DR = 5,
PauseDR = 6,
Exit2DR = 7,
UpdateDR = 8,
SelectIR = 9,
CaptureIR = 10,
ShiftIR = 11,
Exit1IR = 12,
PauseIR = 13,
Exit2IR = 14,
UpdateIR = 15,
}
pub trait Backend {
#[doc(hidden)]
fn into_interface(self) -> Result<Box<dyn JtagInterface>, Error>;
}
pub trait JtagInterface {
fn switch_mode(&mut self, new_state: JtagState, flush: bool) -> Result<(), Error>;
fn mode_reset(&mut self) -> Result<(), Error> {
self.switch_mode(JtagState::Reset, true)
}
fn write_bits(
&mut self,
reg: Register,
bits: &BitVec<u8, Lsb0>,
flush: bool,
) -> Result<(), Error>;
fn read_bits(&mut self, reg: Register, bits: &mut BitVec<u8, Lsb0>) -> Result<(), Error>;
fn read_write_bits(
&mut self,
reg: Register,
read_bits: &mut BitVec<u8, Lsb0>,
write_bits: &BitVec<u8, Lsb0>,
) -> Result<(), Error>;
#[allow(clippy::type_complexity)]
fn batch(
&mut self,
count: usize,
writer: &mut dyn FnMut(usize, &mut BitVec<u8, Lsb0>) -> Result<(), Error>,
reader: &mut dyn FnMut(usize, &BitVec<u8, Lsb0>) -> Result<(), Error>,
) -> Result<(), Error>;
fn write_repeated(&mut self, reg: Register, one_or_zero: u8, bits: usize) -> Result<(), Error> {
let (cnt_blocks, cnt_rem) = (bits / 512, bits % 512);
for _ in 0..cnt_blocks {
let data = BitVec::repeat(one_or_zero > 0, 512);
self.write_bits(reg, &data, true)?;
}
let data = BitVec::repeat(one_or_zero > 0, cnt_rem);
self.write_bits(reg, &data, true)
}
fn measure_ir_len(&mut self) -> Result<usize, Error> {
self.write_repeated(Instruction, 0, 1024)?;
let buf_one = BitVec::repeat(true, 1); let mut buf_read = BitVec::repeat(false, 1);
let mut ir_len = 0;
loop {
self.read_write_bits(Instruction, &mut buf_read, &buf_one)?;
if buf_read[0] {
break;
}
ir_len += 1;
if ir_len > 1024 {
return Error::result(BrokenChain, "TDO holds 0");
}
}
if ir_len < 2 {
return Error::result(BrokenChain, "TDO holds 1");
}
Ok(ir_len)
}
fn measure_dr_len(&mut self) -> Result<usize, Error> {
self.write_repeated(Data, 1, 65536)?;
let buf_zero = BitVec::repeat(false, 1); let mut buf_read = BitVec::repeat(true, 1);
let mut dr_len = 0;
loop {
self.read_write_bits(Data, &mut buf_read, &buf_zero)?;
if !buf_read[0] {
break;
}
dr_len += 1;
if dr_len > 1024 {
return Error::result(BrokenChain, "TDO holds 1");
}
}
if dr_len < 1 {
return Error::result(BrokenChain, "TDO holds 0");
}
Ok(dr_len)
}
}