📄 jtag_chain.c
字号:
{
JTAG_Discover_IR();
// At this point we know num_devices(a global variable) and we know the
// length of each device's IR given in the variable JTAG_info[].IR_length
JTAG_Discover_DR(); // Read and assign the ID for each
// device
} //end discover
//------------------------------------------------------------------------------------
// JTAG_Discover_IR
//------------------------------------------------------------------------------------
// This routine fills a structure with the length of each device's instruction
// register. It also updates the global variable <num_devices> with the number of
// JTAG devices connected in the chain.
//
// BACKGROUND: When an IRSCAN is issued, a JTAG device must return a 1 as the LSB
// and zeros in all the other bits. We shift in all ones so when we
// encounter two ones in a row, we know we are past the end of the chain.
// A state machine is implemented in this routine to keep track of
// inputs received.
//
// STATE DEFINITONS:
// 0 - NO INPUTS -- at beginning of chain
// 1 - INPUT SEQUENCE: 1 -- could be at a new device or at chain end
// 2 - INPUT SEQUENCE: 100..0 -- counting zeros
//
//
void JTAG_Discover_IR(void)
{
char state = 0; // beginning of chain
char num_zeros = 0; // number of zeros following a one in
// an IR_SCAN. num_zeros + 1 = IR_length
char current_device_index = -1; // current_device_index + 1 = num_devices
// (on the last iteration)
bit done = FALSE; // TRUE when end of chain is reached
JTAG_Reset(); // RESET and move to Run_Test/Idle
// advance to Shift_IR State
TMS = 1;
JTAG_StrobeTCK (); // move to SelectDR
TMS = 1;
JTAG_StrobeTCK (); // move to SelectIR
TMS = 0;
JTAG_StrobeTCK (); // move to Capture_IR
TMS = 0;
JTAG_StrobeTCK (); // move to Shift_IR state and get the
// the first input
TDI = 1; // STATE is initially 0
// shift in all ones
// for each device
do{
if(TDO != 1){ // Error if the first input is not one.
Blink_Led(); // Could mean bad connections or
} // non-compliant devices.
state = 1; // received a 1, could be at a new
// device or at the end of the chain
num_zeros = 0; // initialize for the zero counting loop
// for the number of zeros in each device's IR
do {
JTAG_StrobeTCK(); // get the next bit.
switch(state){
case 1: if(TDO == 0){ // found new device(10)
current_device_index++;
num_zeros++;
state = 2;
} else {
done = TRUE; // at end of chain (11)
}
break;
case 2: if(TDO == 0){
num_zeros++; // counting zeros (10..0)
} else {
state = 1; // past end of current device (10..01)
}
break;
default: Blink_Led(); // an error has occurred
} // end switch
} while ((state != 1) && (!done)); // while the input is not one,
// count zeros until we get a one.
if (!done) { // if we are not past the last device
JTAG_info[current_device_index].IR_length = num_zeros + 1;
}
} while (!done); //while we are not past the last device
num_devices = current_device_index + 1;
// navigate the JTAG State Machine back to RTI state.
TMS = 1;
JTAG_StrobeTCK (); // move to Exit1_IR state
TMS = 1;
JTAG_StrobeTCK (); // move to Update_IR state
TMS = 0;
JTAG_StrobeTCK (); // move to Run_Test/Idle state
}
//------------------------------------------------------------------------------------
// JTAG_Discover_DR
//------------------------------------------------------------------------------------
//GOAL: Obtain the ID code of each device(If it supports IDCODE), and fill in
// the field JTAG_info[].id (32-bit).
// Assign all zeros if device does not have an IDCODE.
//
//BACKGROUND: After JTAG State Machine Reset, the IDCODE is automatically selected
// If a device does not have an IDCODE register, the BYPASS
// register is selected instead.
// On a DR_SCAN, each IDCODE register returns a 32-bit ID with LSB = 1
// and each BYPASS register returns 1-bit = 0.
void JTAG_Discover_DR(void)
{
char current_device_index = 0;
unsigned char i; // loop counter
JTAG_Reset (); // Reset the JTAG state machine on DUT
// move to Run_Test/Idle
// The IDCODE or the BYPASS Register is automatically selected.
// Navigate to the Shift_DR state
TMS = 1;
JTAG_StrobeTCK (); // move to SelectDR
TMS = 0;
JTAG_StrobeTCK (); // move to Capture_DR
TMS = 0;
TDI = 1; // shift in all ones
current_device_index = 0;
while (current_device_index < num_devices) {
JTAG_StrobeTCK (); // move to Shift_DR state and get input
if (TDO == 0) { // Device does not have an IDCODE register
JTAG_info[current_device_index].id = 0x00000000L;
} else { // TDO == 1
JTAG_info[current_device_index].id = 0x80000000L;
for (i = 0; i < 31; i++){ // Get the next 31-bits of the device ID
JTAG_StrobeTCK ();
JTAG_info[current_device_index].id =
JTAG_info[current_device_index].id >> 1;
if (TDO) {
JTAG_info[current_device_index].id |= 0x80000000L;
}
} // end for
} // end if-else
current_device_index++;
} // end while
//fill the rest of the entries with zeros
for (; current_device_index < MAX_NUM_DEVICES_IN_CHAIN; current_device_index++) {
JTAG_info[current_device_index].IR_length = 0;
JTAG_info[current_device_index].id = 0x00000000L;
}
// Navigate JTAG State Machine back to RTI state
TMS = 1;
JTAG_StrobeTCK (); // move to Exit1_DR
TMS = 1;
JTAG_StrobeTCK (); // move to Update DR
TMS = 0;
JTAG_StrobeTCK (); // move to RTI
}
//------------------------------------------------------------------------------------
// JTAG_Isolate
//------------------------------------------------------------------------------------
// This routine updates 4 global variables. JTAG_Discover() must be called prior to
// calling this routine in order to set up the data structure.
//
// VARIABLE DEFINITIONS
// num_IR_bits_before -- number of instruction register bits before the isolated
// device
// num_IR_bits_after -- number of instruction register bits after the isolated
// device
// num_devices_before -- number of devices before the isolated device
// num_devices_after -- number of device after the isolated device
//
void JTAG_Isolate(char index)
{
unsigned char i;
if ((index > (num_devices - 1)) || (index < 0) ) {
// check if index is out of range
Blink_Led();
}
num_devices_before = index;
num_devices_after = num_devices - index - 1;
num_IR_bits_before = 0; // initializing for loop
num_IR_bits_after = 0;
for (i = 0; i < num_devices; i++) {
if (i < index) {
num_IR_bits_before += JTAG_info[i].IR_length;
} else if (i > index) {
num_IR_bits_after += JTAG_info[i].IR_length;
}
// last case -- equal, do nothing
} // end for
} //end isolate
//------------------------------------------------------------------------------------
// JTAG_IR_Scan
//------------------------------------------------------------------------------------
// This routine loads the supplied <instruction> of <num_bits> length into the JTAG
// Instruction Register on the isolated device. It shifts the BYPASS opcode (all ones)
// into the Instruction Registers of the other devices in the chain.
//
// NOTE: JTAG_Discover() must be called before this function is called.
//
// NOTE: If more than one device is connected in the chain, JTAG_Isolate() must also
// be called prior to calling this function.
//
// The return value is the n-bit value read from the IR.
// Assumes the JTAG state machine starts in the Run_Test/Idle state.
// Leaves JTAG in the Run_Test/Idle state.
//
unsigned long JTAG_IR_Scan (unsigned long instruction, char num_bits)
{
unsigned long retval; // JTAG instruction read
char i; // JTAG IR bit counter
retval = 0x0L;
// navigate the JTAG State Machine in all devices to the Shift_IR state
TMS = 1;
JTAG_StrobeTCK (); // move to SelectDR
TMS = 1;
JTAG_StrobeTCK (); // move to SelectIR
TMS = 0;
JTAG_StrobeTCK (); // move to Capture_IR
TMS = 0;
JTAG_StrobeTCK (); // move to Shift_IR state
TDI=1;
for (i=0; i < num_IR_bits_before; i++) {
JTAG_StrobeTCK(); // fill the IR of the devices
// before the isolated device
} // with all ones, the BYPASS opcode
for (i=0; i < num_bits; i++) {
TDI = (instruction & 0x01); // determine output
instruction = instruction >> 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -