Line 1... |
Line 1... |
/* adv_dbg_commands.c -- JTAG protocol bridge between GDB and Advanced debug module.
|
/* adv_dbg_commands.c -- JTAG protocol bridge between GDB and Advanced debug module.
|
Copyright(C) Nathan Yawn, nyawn@opencores.net
|
Copyright (C) 2008-2010 Nathan Yawn, nyawn@opencores.net
|
|
|
This file contains functions which perform high-level transactions
|
This file contains functions which perform high-level transactions
|
on a JTAG chain and debug unit, such as setting a value in the TAP IR
|
on a JTAG chain and debug unit, such as setting a value in the TAP IR
|
or doing a burst write through the wishbone module of the debug unit.
|
or doing a burst write through the wishbone module of the debug unit.
|
It uses the protocol for the Advanced Debug Interface (adv_dbg_if).
|
It uses the protocol for the Advanced Debug Interface (adv_dbg_if).
|
Line 24... |
Line 24... |
|
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h> // for malloc()
|
#include <stdlib.h> // for malloc()
|
#include <unistd.h> // for exit()
|
#include <unistd.h> // for exit()
|
//#include <pthread.h> // for mutexes
|
#include <strings.h> // for bzero()
|
|
|
#include "chain_commands.h"
|
#include "chain_commands.h"
|
#include "adv_dbg_commands.h" // hardware-specific defines for the debug module
|
#include "adv_dbg_commands.h" // hardware-specific defines for the debug module
|
//#include "altera_virtual_jtag.h" // hardware-specifg defines for the Altera Virtual JTAG interface
|
|
#include "cable_common.h" // low-level JTAG IO routines
|
#include "cable_common.h" // low-level JTAG IO routines
|
#include "errcodes.h"
|
#include "errcodes.h"
|
|
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
|
|
Line 121... |
Line 120... |
return err;
|
return err;
|
|
|
debug("selreg %ld\n", regidx);
|
debug("selreg %ld\n", regidx);
|
|
|
// If this reg is already selected, don't do a JTAG transaction
|
// If this reg is already selected, don't do a JTAG transaction
|
if((current_chain >= 0) && (current_reg_idx[current_chain] == regidx))
|
if(current_reg_idx[current_chain] == regidx)
|
return APP_ERR_NONE;
|
return APP_ERR_NONE;
|
|
|
switch(current_chain) {
|
switch(current_chain) {
|
case DC_WISHBONE:
|
case DC_WISHBONE:
|
index_len = DBG_WB_REG_SEL_LEN;
|
index_len = DBG_WB_REG_SEL_LEN;
|
Line 343... |
Line 342... |
uint32_t in_data;
|
uint32_t in_data;
|
unsigned long addr;
|
unsigned long addr;
|
uint32_t err_data[2];
|
uint32_t err_data[2];
|
int bus_error_retries = 0;
|
int bus_error_retries = 0;
|
int err = APP_ERR_NONE;
|
int err = APP_ERR_NONE;
|
|
static char *output_scratchpad = NULL;
|
|
static int output_scratchpad_size = 0;
|
|
|
debug("Doing burst read, word size %d, word count %d, start address 0x%lX", word_size_bytes, word_count, start_address);
|
debug("Doing burst read, word size %d, word count %d, start address 0x%lX", word_size_bytes, word_count, start_address);
|
|
|
if(word_count <= 0) {
|
if(word_count <= 0) {
|
debug("Ignoring illegal read burst length (%d)\n", word_count);
|
debug("Ignoring illegal read burst length (%d)\n", word_count);
|
Line 395... |
Line 396... |
|
|
// Send the BURST READ command, returns TAP to idle state
|
// Send the BURST READ command, returns TAP to idle state
|
if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry
|
if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry
|
return err;
|
return err;
|
|
|
// This is a kludge to word around oddities in the Xilinx BSCAN_* devices, and the
|
// This is a kludge to work around oddities in the Xilinx BSCAN_* devices, and the
|
// adv_dbg_if state machine. The debug FSM needs 1 TCK between UPDATE_DR above, and
|
// adv_dbg_if state machine. The debug FSM needs 1 TCK between UPDATE_DR above, and
|
// the CAPTURE_DR below, and the BSCAN_* won't provide it. So, we force it, by putting the TAP
|
// the CAPTURE_DR below, and the BSCAN_* won't provide it. So, we force it, by putting the TAP
|
// in BYPASS, which makes the debug_select line inactive, which is AND'ed with the TCK line (in the xilinx_internal_jtag module),
|
// in BYPASS, which makes the debug_select line inactive, which is AND'ed with the TCK line (in the xilinx_internal_jtag module),
|
// which forces it low. Then we re-enable USER1/debug_select to make TCK high. One TCK
|
// which forces it low. Then we re-enable USER1/debug_select to make TCK high. One TCK
|
// event, the hard way.
|
// event, the hard way.
|
Line 412... |
Line 413... |
err |= tap_set_shift_dr();
|
err |= tap_set_shift_dr();
|
|
|
// We do not adjust for the DR length here. BYPASS regs are loaded with 0,
|
// We do not adjust for the DR length here. BYPASS regs are loaded with 0,
|
// and the debug unit waits for a '1' status bit before beginning to read data.
|
// and the debug unit waits for a '1' status bit before beginning to read data.
|
|
|
|
#ifdef ADBG_OPT_HISPEED
|
|
// Get 1 status bit, then word_size_bytes*8 bits
|
|
status = 0;
|
|
j = 0;
|
|
while(!status) { // Status indicates whether there is a word available to read. Wait until it returns true.
|
|
err |= jtag_read_write_bit(0, &status);
|
|
j++;
|
|
// If max count exceeded, retry
|
|
if(j > MAX_READ_STATUS_WAIT) {
|
|
printf("Burst read timed out.\n");
|
|
if(!retry_do()) {
|
|
printf("Retry count exceeded in burst read!\n");
|
|
return err|APP_ERR_MAX_RETRY;
|
|
}
|
|
err = APP_ERR_NONE; // on retry, errors cleared
|
|
goto wb_burst_read_retry_full;
|
|
}
|
|
}
|
|
|
|
// Check we have enough space for the (zero) output data
|
|
if(output_scratchpad_size < (word_count*word_size_bytes))
|
|
{
|
|
free(output_scratchpad);
|
|
output_scratchpad = (char *) malloc(word_count*word_size_bytes);
|
|
if(output_scratchpad != NULL) {
|
|
output_scratchpad_size = (word_count*word_size_bytes);
|
|
bzero(output_scratchpad, output_scratchpad_size);
|
|
}
|
|
else {
|
|
output_scratchpad_size = 0;
|
|
return APP_ERR_MALLOC;
|
|
}
|
|
}
|
|
//uint32_t outstream[64];
|
|
//bzero((char *)outstream, 64*4);
|
|
|
|
// Get the data in one shot
|
|
err |= jtag_read_write_stream((uint32_t *)output_scratchpad, (uint32_t *)data, word_size_bits*word_count, 0, 0);
|
|
for(i = 0; i < (word_count*word_size_bytes); i++)
|
|
{
|
|
crc_calc = adbg_compute_crc(crc_calc, ((uint8_t *)data)[i], 8);
|
|
}
|
|
#else
|
|
|
// Repeat for each word: wait until ready = 1, then read word_size_bits bits.
|
// Repeat for each word: wait until ready = 1, then read word_size_bits bits.
|
for(; i < word_count; i++)
|
for(; i < word_count; i++)
|
{
|
{
|
// Get 1 status bit, then word_size_bytes*8 bits
|
// Get 1 status bit, then word_size_bytes*8 bits
|
status = 0;
|
status = 0;
|
Line 459... |
Line 504... |
|
|
if(word_size_bytes == 1) ((unsigned char *)data)[i] = in_data & 0xFF;
|
if(word_size_bytes == 1) ((unsigned char *)data)[i] = in_data & 0xFF;
|
else if(word_size_bytes == 2) ((unsigned short *)data)[i] = in_data & 0xFFFF;
|
else if(word_size_bytes == 2) ((unsigned short *)data)[i] = in_data & 0xFFFF;
|
else ((unsigned long *)data)[i] = in_data;
|
else ((unsigned long *)data)[i] = in_data;
|
}
|
}
|
|
#endif
|
|
|
// All bus data was read. Read the data CRC from the debug module.
|
// All bus data was read. Read the data CRC from the debug module.
|
err |= jtag_read_write_stream(&out_data, &crc_read, 32, 0, 1);
|
err |= jtag_read_write_stream(&out_data, &crc_read, 32, 0, 1);
|
|
|
err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE
|
err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE
|
Line 476... |
Line 522... |
goto wb_burst_read_retry_full;
|
goto wb_burst_read_retry_full;
|
}
|
}
|
else debug("CRC OK!");
|
else debug("CRC OK!");
|
|
|
|
|
|
|
// Now, read the error register, and retry/recompute as necessary.
|
// Now, read the error register, and retry/recompute as necessary.
|
if(current_chain == DC_WISHBONE)
|
if(current_chain == DC_WISHBONE)
|
{
|
{
|
err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1); // First, just get 1 bit...read address only if necessary,
|
err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1); // First, just get 1 bit...read address only if necessary,
|
if(err_data[0] & 0x1) { // Then we have a problem.
|
if(err_data[0] & 0x1) { // Then we have a problem.
|
Line 506... |
Line 551... |
|
|
// Set up and execute a burst write to a contiguous set of addresses
|
// Set up and execute a burst write to a contiguous set of addresses
|
int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address)
|
int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address)
|
{
|
{
|
unsigned char opcode;
|
unsigned char opcode;
|
uint8_t status;
|
|
uint32_t datawords[2] = {0,0};
|
uint32_t datawords[2] = {0,0};
|
uint32_t statuswords[2] = {0,0};
|
|
int i;
|
int i;
|
uint32_t crc_calc;
|
uint32_t crc_calc;
|
uint32_t crc_match;
|
uint32_t crc_match;
|
unsigned int word_size_bits;
|
unsigned int word_size_bits;
|
unsigned long addr;
|
unsigned long addr;
|
int bus_error_retries = 0;
|
int bus_error_retries = 0;
|
uint32_t err_data[2];
|
uint32_t err_data[2];
|
int loopct, successes;
|
int loopct, successes;
|
int first_status_loop;
|
#ifndef ADBG_OPT_HISPEED
|
|
uint8_t status;
|
|
uint32_t statuswords[2] = {0,0};
|
|
int first_status_loop = 1;
|
|
#endif
|
int err = APP_ERR_NONE;
|
int err = APP_ERR_NONE;
|
|
|
debug("Doing burst write, word size %d, word count %d, start address 0x%lx", word_size_bytes, word_count, start_address);
|
debug("Doing burst write, word size %d, word count %d, start address 0x%lx\n", word_size_bytes, word_count, start_address);
|
word_size_bits = word_size_bytes << 3;
|
word_size_bits = word_size_bytes << 3;
|
|
|
if(word_count <= 0) {
|
if(word_count <= 0) {
|
printf("Ignoring illegal burst write size (%d)\n", word_count);
|
printf("Ignoring illegal burst write size (%d)\n", word_count);
|
return 0;
|
return 0;
|
Line 558... |
Line 605... |
default:
|
default:
|
printf("ERROR! Illegal debug chain selected while doing burst WRITE!\n");
|
printf("ERROR! Illegal debug chain selected while doing burst WRITE!\n");
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
#ifndef ADBG_OPT_HISPEED
|
// Compute which loop iteration in which to expect the first status bit
|
// Compute which loop iteration in which to expect the first status bit
|
first_status_loop = 1 + ((global_DR_prefix_bits + global_DR_postfix_bits)/(word_size_bits+1));
|
first_status_loop = 1 + ((global_DR_prefix_bits + global_DR_postfix_bits)/(word_size_bits+1));
|
|
#endif
|
|
|
wb_burst_write_retry_full:
|
wb_burst_write_retry_full:
|
i = 0;
|
i = 0;
|
addr = start_address;
|
addr = start_address;
|
wb_burst_write_retry_partial:
|
wb_burst_write_retry_partial:
|
Line 574... |
Line 623... |
// Send burst command, return to idle state
|
// Send burst command, return to idle state
|
if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry
|
if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry
|
return err;
|
return err;
|
|
|
// Get us back to shift_dr mode to write a burst
|
// Get us back to shift_dr mode to write a burst
|
//err |= jtag_write_bit(TMS); // select_dr_scan
|
|
//err |= jtag_write_bit(0); // capture_ir
|
|
//err |= jtag_write_bit(0); // shift_ir
|
|
err |= tap_set_shift_dr();
|
err |= tap_set_shift_dr();
|
|
|
// Write a start bit (a 1) so it knows when to start counting
|
// Write a start bit (a 1) so it knows when to start counting
|
err |= jtag_write_bit(TDO);
|
err |= jtag_write_bit(TDO);
|
|
|
|
#ifdef ADBG_OPT_HISPEED
|
|
// If compiled for "hi-speed" mode, we don't read a status bit after every
|
|
// word written. This saves a lot of complication!
|
|
// In this case, the loop below is used only for CRC calculation.
|
|
err |= jtag_write_stream((uint32_t *) data, (word_count*word_size_bits), 0); // Write data
|
|
#endif
|
|
|
// Now, repeat...
|
// Now, repeat...
|
for(loopct = 0; i < word_count; i++,loopct++) // loopct only used to check status...
|
for(loopct = 0; i < word_count; i++,loopct++) // loopct only used to check status...
|
{
|
{
|
// Write word_size_bytes*8 bits, then get 1 status bit
|
// Write word_size_bytes*8 bits, then get 1 status bit
|
if(word_size_bytes == 4) datawords[0] = ((unsigned long *)data)[i];
|
if(word_size_bytes == 4) datawords[0] = ((unsigned long *)data)[i];
|
else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[i];
|
else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[i];
|
else datawords[0] = ((unsigned char *)data)[i];
|
else datawords[0] = ((unsigned char *)data)[i];
|
|
|
crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits);
|
crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits);
|
|
|
|
#ifndef ADBG_OPT_HISPEED
|
// This is an optimization
|
// This is an optimization
|
if((global_DR_prefix_bits + global_DR_postfix_bits) == 0) {
|
if((global_DR_prefix_bits + global_DR_postfix_bits) == 0) {
|
|
//#endif
|
err |= jtag_write_stream(datawords, word_size_bits, 0); // Write data
|
err |= jtag_write_stream(datawords, word_size_bits, 0); // Write data
|
|
//#ifndef ADBG_OPT_HISPEED
|
err |= jtag_read_write_bit(0, &status); // Read status bit
|
err |= jtag_read_write_bit(0, &status); // Read status bit
|
if(!status) {
|
if(!status) {
|
addr = start_address + (i*word_size_bytes);
|
addr = start_address + (i*word_size_bytes);
|
printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr);
|
printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr);
|
if(!retry_do()) { printf("Retry count exceeded! Abort!\n\n"); exit(1);}
|
if(!retry_do()) { printf("Retry count exceeded! Abort!\n\n"); exit(1);}
|
Line 620... |
Line 676... |
// Don't bother going to TAP idle state, we're about to reset the TAP
|
// Don't bother going to TAP idle state, we're about to reset the TAP
|
goto wb_burst_write_retry_partial;
|
goto wb_burst_write_retry_partial;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
#endif
|
|
|
if(err) {
|
if(err) {
|
printf("Error %s getting status bit, retrying.\n", get_err_string(err));
|
printf("Error %s during burst write, retrying.\n", get_err_string(err));
|
if(!retry_do()) {
|
if(!retry_do()) {
|
printf("Retry count exceeded!\n");
|
printf("Retry count exceeded!\n");
|
return err|APP_ERR_MAX_RETRY;
|
return err|APP_ERR_MAX_RETRY;
|
}
|
}
|
err = APP_ERR_NONE;
|
err = APP_ERR_NONE;
|
Line 636... |
Line 693... |
}
|
}
|
|
|
debug("Wrote 0x%0lx", datawords[0]);
|
debug("Wrote 0x%0lx", datawords[0]);
|
}
|
}
|
|
|
// *** If this is a multi-device chain, at least one status bit will be lost.
|
// *** If this is a multi-device chain (and we're not in hi-speed mode), at least one status bit will be lost.
|
// *** If we want to check for it, we'd have to look while sending the CRC, and
|
// *** If we want to check for it, we'd have to look while sending the CRC, and
|
// *** maybe while burning bits to get the match bit. So, for now, there is a
|
// *** maybe while burning bits to get the match bit. So, for now, there is a
|
// *** hole here.
|
// *** hole here.
|
|
|
// Done sending data, Send the CRC we computed
|
// Done sending data, Send the CRC we computed
|