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 <strings.h> // for bzero()
|
#include <string.h> // for memcpy()
|
|
|
#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 "cable_common.h" // low-level JTAG IO routines
|
#include "cable_common.h" // low-level JTAG IO routines
|
#include "errcodes.h"
|
#include "errcodes.h"
|
|
#include "utilities.h"
|
|
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
|
|
// How many '0' status bits to get during a burst read
|
// How many '0' status bits to get during a burst read
|
// before giving up
|
// before giving up
|
Line 41... |
Line 42... |
|
|
// Currently selected internal register in each module
|
// Currently selected internal register in each module
|
// - cuts down on unnecessary transfers
|
// - cuts down on unnecessary transfers
|
int current_reg_idx[DBG_MAX_MODULES];
|
int current_reg_idx[DBG_MAX_MODULES];
|
|
|
|
// Scratchpad I/O buffers
|
|
static char *input_scratchpad = NULL;
|
|
static char *output_scratchpad = NULL;
|
|
static int input_scratchpad_size = 0;
|
|
static int output_scratchpad_size = 0;
|
|
|
// Prototypes for local functions
|
// Prototypes for local functions
|
uint32_t adbg_compute_crc(uint32_t crc_in, uint32_t data_in, int length_bits);
|
uint32_t adbg_compute_crc(uint32_t crc_in, uint32_t data_in, int length_bits);
|
|
|
|
|
|
|
Line 342... |
Line 349... |
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 433... |
Line 438... |
goto wb_burst_read_retry_full;
|
goto wb_burst_read_retry_full;
|
}
|
}
|
}
|
}
|
|
|
// Check we have enough space for the (zero) output data
|
// Check we have enough space for the (zero) output data
|
if(output_scratchpad_size < (word_count*word_size_bytes))
|
int total_size_bytes = (word_count*word_size_bytes)+4;
|
{
|
err |= check_buffer_size(&input_scratchpad, &input_scratchpad_size, total_size_bytes);
|
free(output_scratchpad);
|
err |= check_buffer_size(&output_scratchpad, &output_scratchpad_size, total_size_bytes);
|
output_scratchpad = (char *) malloc(word_count*word_size_bytes);
|
if(err != APP_ERR_NONE) return err;
|
if(output_scratchpad != NULL) {
|
memset(output_scratchpad, 0, total_size_bytes);
|
output_scratchpad_size = (word_count*word_size_bytes);
|
|
bzero(output_scratchpad, output_scratchpad_size);
|
// Get the data in one shot, including the CRC. This requires two memcpy(), which take time,
|
}
|
// but it's still faster than an added USB transaction (assuming a USB cable).
|
else {
|
err |= jtag_read_write_stream((uint32_t *)output_scratchpad, (uint32_t *)input_scratchpad, (total_size_bytes*8), 0, 1);
|
output_scratchpad_size = 0;
|
memcpy(data, input_scratchpad, (word_count*word_size_bytes));
|
return APP_ERR_MALLOC;
|
memcpy(&crc_read, &input_scratchpad[(word_count*word_size_bytes)], 4);
|
}
|
|
}
|
|
//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++)
|
for(i = 0; i < (word_count*word_size_bytes); i++)
|
{
|
{
|
crc_calc = adbg_compute_crc(crc_calc, ((uint8_t *)data)[i], 8);
|
crc_calc = adbg_compute_crc(crc_calc, ((uint8_t *)data)[i], 8);
|
}
|
}
|
|
|
#else
|
#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++)
|
{
|
{
|
Line 504... |
Line 503... |
|
|
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);
|
|
|
|
#endif
|
|
|
err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE
|
err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE
|
|
|
if(crc_calc != crc_read) {
|
if(crc_calc != crc_read) {
|
printf("CRC ERROR! Computed 0x%x, read CRC 0x%x\n", crc_calc, crc_read);
|
printf("CRC ERROR! Computed 0x%x, read CRC 0x%x\n", crc_calc, crc_read);
|
if(!retry_do()) {
|
if(!retry_do()) {
|
Line 631... |
Line 631... |
err |= jtag_write_bit(TDO);
|
err |= jtag_write_bit(TDO);
|
|
|
#ifdef ADBG_OPT_HISPEED
|
#ifdef ADBG_OPT_HISPEED
|
// If compiled for "hi-speed" mode, we don't read a status bit after every
|
// If compiled for "hi-speed" mode, we don't read a status bit after every
|
// word written. This saves a lot of complication!
|
// word written. This saves a lot of complication!
|
// In this case, the loop below is used only for CRC calculation.
|
// We send the CRC at the same time, so we have to compute it first.
|
err |= jtag_write_stream((uint32_t *) data, (word_count*word_size_bits), 0); // Write data
|
for(loopct = 0; loopct < word_count; loopct++) {
|
#endif
|
if(word_size_bytes == 4) datawords[0] = ((unsigned long *)data)[loopct];
|
|
else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[loopct];
|
|
else datawords[0] = ((unsigned char *)data)[loopct];
|
|
crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits);
|
|
}
|
|
|
|
int total_size_bytes = (word_count * word_size_bytes) + 4;
|
|
err |= check_buffer_size(&output_scratchpad, &output_scratchpad_size, total_size_bytes);
|
|
if(err != APP_ERR_NONE) return err;
|
|
|
|
memcpy(output_scratchpad, data, (word_count * word_size_bytes));
|
|
memcpy(&output_scratchpad[(word_count*word_size_bytes)], &crc_calc, 4);
|
|
|
|
err |= jtag_write_stream((uint32_t *) output_scratchpad, total_size_bytes*8, 0); // Write data
|
|
|
// Now, repeat...
|
#else
|
|
|
|
// Or, 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
|
//#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
|
//#ifndef ADBG_OPT_HISPEED
|
Line 676... |
Line 690... |
// 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 during burst write, 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");
|
Line 700... |
Line 713... |
// *** 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
|
err |= jtag_write_stream(&crc_calc, 32, 0);
|
err |= jtag_write_stream(&crc_calc, 32, 0);
|
|
|
|
#endif
|
|
|
for(i = 0; i < global_DR_prefix_bits; i++) // Push the CRC data all the way to the debug unit
|
for(i = 0; i < global_DR_prefix_bits; i++) // Push the CRC data all the way to the debug unit
|
err |= jtag_write_bit(0); // Can't do this with a stream command without setting TMS on the last bit
|
err |= jtag_write_bit(0); // Can't do this with a stream command without setting TMS on the last bit
|
|
|
// Read the 'CRC match' bit, and go to exit1_dr
|
// Read the 'CRC match' bit, and go to exit1_dr
|
// May need to adjust for other devices in chain!
|
// May need to adjust for other devices in chain!
|
Line 743... |
Line 759... |
|
|
retry_ok();
|
retry_ok();
|
return err;
|
return err;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|
|
/*--------------------------------------------------------------------------------------------*/
|
|
|
|
// This does a simultaneous read/write to the JTAG serial port. It will send/receive at most 8 bytes,
|
|
// so data_received must be at least 8 bytes long. It is not guaranteed that all data (or any data)
|
|
// will be sent. On return, bytes_to_send will be set to the number of bytes actually senet.
|
|
|
|
int adbg_jsp_transact(unsigned int *bytes_to_send, const char *data_to_send, unsigned int *bytes_received, char *data_received)
|
|
{
|
|
int err = APP_ERR_NONE;
|
|
unsigned int xmitsize;
|
|
char outdata[10]; // These must 10 bytes: 1 for counts, 8 for data, and 1 (possible) start and end bits
|
|
char indata[10];
|
|
unsigned char stopbit = 0, startbit = 0, wrapbit;
|
|
int bytes_free;
|
|
int i;
|
|
|
|
if(*bytes_to_send > 8)
|
|
xmitsize = 8;
|
|
else
|
|
xmitsize = *bytes_to_send;
|
|
|
|
if(err |= adbg_select_module(desired_chain))
|
|
return err;
|
|
|
|
// Put us in shift_dr mode
|
|
err |= tap_set_shift_dr();
|
|
|
|
// There are two independant compile-time options here, making four different ways to do this transaction.
|
|
// If OPTIMIZE_FOR_USB is not defined, then one byte will be transacted to get the 'bytes available' and
|
|
// 'bytes free' counts, then the minimum number of bytes will be transacted to get all available bytes
|
|
// and put as many bytes as possible. If OPTIMIZE_FOR_USB is defined, then 9 bytes will always be transacted,
|
|
// the JSP will ignore extras, and user code will have to check to see how many bytes were written.
|
|
//
|
|
// if ENABLE_JSP_MULTI is enabled, then a '1' bit will be pre-pended to the data being sent (before the 'count'
|
|
// byte). This is for compatibility with multi-device JTAG chains.
|
|
|
|
#ifdef OPTIMIZE_JSP_FOR_USB
|
|
|
|
// Simplest case: do everything in 1 burst transaction
|
|
memset(outdata, 0, 10); // Clear to act as 'stopbits'. [8] may be overwritten in the following memcpy().
|
|
|
|
#ifdef ENABLE_JSP_MULTI
|
|
|
|
startbit = 1;
|
|
wrapbit = (xmitsize >> 3) & 0x1;
|
|
outdata[0] = (xmitsize << 5) | 0x1; // set the start bit
|
|
|
|
for(i = 0; i < xmitsize; i++) // don't copy off the end of the input array
|
|
{
|
|
outdata[i+1] = (data_to_send[i] << 1) | wrapbit;
|
|
wrapbit = (data_to_send[i] >> 7) & 0x1;
|
|
}
|
|
|
|
if(i < 8)
|
|
outdata[i+1] = wrapbit;
|
|
else
|
|
outdata[9] = wrapbit;
|
|
|
|
// If the last data bit is a '1', then we need to append a '0' so the top-level module
|
|
// won't treat the burst as a 'module select' command.
|
|
if(outdata[9] & 0x01) stopbit = 1;
|
|
else stopbit = 0;
|
|
|
|
#else
|
|
|
|
startbit = 0;
|
|
outdata[0] = 0x0 | (xmitsize << 4); // First byte out has write count in upper nibble
|
|
if (xmitsize > 0) memcpy(&outdata[1], data_to_send, xmitsize);
|
|
|
|
// If the last data bit is a '1', then we need to append a '0' so the top-level module
|
|
// won't treat the burst as a 'module select' command.
|
|
if(outdata[8] & 0x80) stopbit = 1;
|
|
else stopbit = 0;
|
|
|
|
#endif
|
|
|
|
debug("jsp doing 9 bytes, xmitsize %i\n", xmitsize);
|
|
|
|
// 72 bits: 9 bytes * 8 bits
|
|
err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, 72+startbit+stopbit, 1, 1);
|
|
|
|
debug("jsp got remote sizes 0x%X\n", indata[0]);
|
|
|
|
*bytes_received = (indata[0] >> 4) & 0xF; // bytes available is in the upper nibble
|
|
memcpy(data_received, &indata[1], *bytes_received);
|
|
|
|
bytes_free = indata[0] & 0x0F;
|
|
*bytes_to_send = (bytes_free < xmitsize) ? bytes_free : xmitsize;
|
|
|
|
#else // !OPTIMIZE_JSP_FOR_USB
|
|
|
|
#ifdef ENABLE_JSP_MULTI
|
|
indata[0] = indata[1] = 0;
|
|
outdata[1] = (xmitsize >> 3) & 0x1;
|
|
outdata[0] = (xmitsize << 5) | 0x1; // set the start bit
|
|
startbit = 1;
|
|
|
|
#else
|
|
outdata[0] = 0x0 | (xmitsize << 4); // First byte out has write count in upper nibble
|
|
startbit = 0;
|
|
#endif
|
|
|
|
err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, 8+startbit, 1, 0);
|
|
|
|
wrapbit = indata[1] & 0x1; // only used if ENABLE_JSP_MULTI is defined
|
|
bytes_free = indata[0] & 0x0F;
|
|
*bytes_received = (indata[0] >> 4) & 0xF; // bytes available is in the upper nibble
|
|
|
|
// Number of bytes to transact is max(bytes_available, min(bytes_to_send,bytes_free))
|
|
if(bytes_free < xmitsize) xmitsize = bytes_free;
|
|
if((*bytes_received) > xmitsize) xmitsize = *bytes_received;
|
|
|
|
memset(outdata, 0, 10);
|
|
memcpy(outdata, data_to_send, xmitsize); // use larger array in case we need to send stopbit
|
|
|
|
// If the last data bit is a '1', then we need to append a '0' so the top-level module
|
|
// won't treat the burst as a 'module select' command.
|
|
if(xmitsize && (outdata[xmitsize - 1] & 0x80)) stopbit = 2;
|
|
else stopbit = 1;
|
|
|
|
err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, (xmitsize*8)+stopbit, 0, 1);
|
|
|
|
#ifdef ENABLE_JSP_MULTI
|
|
|
|
for(i = 0; i < (*bytes_received); i++)
|
|
{
|
|
data_received[i] = (indata[i] << 1) | wrapbit;
|
|
wrapbit = (indata[i] >> 7) & 0x1;
|
|
}
|
|
#else
|
|
memcpy(data_received, indata, xmitsize);
|
|
#endif
|
|
|
|
if(bytes_free < *bytes_to_send) *bytes_to_send = bytes_free;
|
|
|
|
#endif // !OPTIMIZE_JSP_FOR_USB
|
|
|
|
err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE
|
|
|
|
return err;
|
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|