Retire jtag_add_dr_out

The out only version of jtag_add_dr_scan smells like a bogus optimization
that complicates the minidriver API for questionable gain.

The function was only used by four old ARM targets. Rewrite the callers
to use the generic function and remove all implementations.

Change-Id: I13b643687ee8ed6bc9b6336e7096c34f40ea96af
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/1801
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
Andreas Fritiofson 2013-11-07 00:40:50 +01:00 committed by Spencer Oliver
parent 87e91f4db9
commit 63fa73169b
12 changed files with 59 additions and 271 deletions

View File

@ -193,92 +193,6 @@ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
return ERROR_OK;
}
/**
* Generate a DR SCAN using the array of output values passed to the function
*
* This function assumes that the parameter target_tap specifies the one TAP
* that is not bypassed. All other TAPs must be bypassed and the function will
* generate a dummy 1bit field for them.
*
* For the target_tap a sequence of output-only fields will be generated where
* each field has the size num_bits and the field's values are taken from
* the array value.
*
* The bypass status of TAPs is set by jtag_add_ir_scan().
*
*/
void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
int in_num_fields,
const int *num_bits,
const uint32_t *value,
tap_state_t end_state)
{
/* count devices in bypass */
size_t bypass_devices = 0;
for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
if (tap->bypass)
bypass_devices++;
}
struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
jtag_queue_command(cmd);
cmd->type = JTAG_SCAN;
cmd->cmd.scan = scan;
scan->ir_scan = false;
scan->num_fields = in_num_fields + bypass_devices;
scan->fields = out_fields;
scan->end_state = end_state;
bool target_tap_match = false;
struct scan_field *field = out_fields; /* keep track where we insert data */
/* loop over all enabled TAPs */
for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
/* if TAP is not bypassed insert matching input fields */
if (!tap->bypass) {
assert(tap == target_tap); /* target_tap must match the one not bypassed TAP */
target_tap_match = true;
for (int j = 0; j < in_num_fields; j++) {
uint8_t out_value[4];
size_t scan_size = num_bits[j];
buf_set_u32(out_value, 0, scan_size, value[j]);
field->num_bits = scan_size;
field->out_value = buf_cpy(out_value, cmd_queue_alloc(DIV_ROUND_UP(scan_size, 8)), scan_size);
field->in_value = NULL;
field++;
}
}
/* if a TAP is bypassed, generated a dummy bit*/
else {
field->num_bits = 1;
field->out_value = NULL;
field->in_value = NULL;
field++;
}
}
assert(target_tap_match); /* target_tap should be enabled and not bypassed */
}
static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
uint8_t *in_bits, tap_state_t state, bool ir_scan)
{
@ -496,21 +410,6 @@ void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t
jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
}
/* A minidriver can use use an inline versions of this API level fn */
void jtag_add_dr_out(struct jtag_tap *tap,
int num_fields, const int *num_bits, const uint32_t *value,
tap_state_t end_state)
{
assert(end_state != TAP_RESET);
assert(end_state != TAP_INVALID);
cmd_queue_cur_state = end_state;
interface_jtag_add_dr_out(tap,
num_fields, num_bits, value,
end_state);
}
void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
{
interface_jtag_add_callback(f, data0);

View File

@ -29,21 +29,12 @@ static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field)
field->in_value = cmd_queue_alloc(num_bytes);
}
void interface_jtag_add_dr_out(struct jtag_tap *tap,
int num_fields, const int *num_bits, const uint32_t *value,
tap_state_t end_state);
void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0);
void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
jtag_callback_data_t data1, jtag_callback_data_t data2,
jtag_callback_data_t data3);
void jtag_add_dr_out(struct jtag_tap *tap,
int num_fields, const int *num_bits, const uint32_t *value,
tap_state_t end_state);
void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
jtag_callback_data_t data1, jtag_callback_data_t data2,
jtag_callback_data_t data3);

View File

@ -609,33 +609,6 @@ void jtag_sleep(uint32_t us);
#define ERROR_JTAG_TRANSITION_INVALID (-109)
#define ERROR_JTAG_INIT_SOFT_FAIL (-110)
/**
* jtag_add_dr_out() is a version of jtag_add_dr_scan() which
* only scans data out. It operates on 32 bit integers instead
* of 8 bit, which makes it a better impedance match with
* the calling code which often operate on 32 bit integers.
*
* Current or end_state can not be TAP_RESET. end_state can be TAP_INVALID
*
* num_bits[i] is the number of bits to clock out from value[i] LSB first.
*
* If the device is in bypass, then that is an error condition in
* the caller code that is not detected by this fn, whereas
* jtag_add_dr_scan() does detect it. Similarly if the device is not in
* bypass, data must be passed to it.
*
* If anything fails, then jtag_error will be set and jtag_execute() will
* return an error. There is no way to determine if there was a failure
* during this function call.
*
* This is an inline fn to speed up embedded hosts. Also note that
* interface_jtag_add_dr_out() can be a *small* inline function for
* embedded hosts.
*
* There is no jtag_add_dr_outin() version of this fn that also allows
* clocking data back in. Patches gladly accepted!
*/
/**
* Set the current JTAG core execution error, unless one was set
* by a previous call previously. Driver or application code must

View File

@ -39,7 +39,6 @@
* define static inline versions of them):
* - jtag_add_callback
* - jtag_add_callback4
* - interface_jtag_add_dr_out
*
* The following core functions are declared in this file for use by
* the minidriver and do @b not need to be defined by an implementation:

View File

@ -24,17 +24,6 @@
#include <jtag/jtag_minidriver.h>
static inline void jtag_add_dr_out(struct jtag_tap *tap,
int num_fields, const int *num_bits, const uint32_t *value,
tap_state_t end_state)
{
cmd_queue_cur_state = end_state;
interface_jtag_add_dr_out(tap,
num_fields, num_bits, value,
end_state);
}
#define jtag_add_callback(callback, in) interface_jtag_add_callback(callback, in)
#define jtag_add_callback4(callback, in, data1, data2, data3) \

View File

@ -17,24 +17,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
static inline void interface_jtag_add_dr_out_core(struct jtag_tap *targettap,
int num_fields,
const int *num_bits,
const uint32_t *value,
enum tap_state end_state)
{
/* synchronously do the operation here */
}
static inline void interface_jtag_add_dr_out(struct jtag_tap *targettap,
int num_fields,
const int *num_bits,
const uint32_t *value,
enum tap_state end_state)
{
/* synchronously do the operation here */
}
#define interface_jtag_add_callback(callback, in) callback(in)
#define interface_jtag_add_callback4(callback, in, data1, data2, data3) \

View File

@ -169,52 +169,6 @@ static inline void shiftValueInner(const enum tap_state state,
#endif
}
static inline void interface_jtag_add_dr_out_core(struct jtag_tap *target_tap,
int num_fields,
const int *num_bits,
const uint32_t *value,
enum tap_state end_state)
{
enum tap_state pause_state = TAP_DRSHIFT;
struct jtag_tap *tap, *nextTap;
for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) {
nextTap = jtag_tap_next_enabled(tap);
if (nextTap == NULL)
pause_state = end_state;
if (tap == target_tap) {
int j;
for (j = 0; j < (num_fields-1); j++)
shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[j], value[j]);
shiftValueInner(TAP_DRSHIFT, pause_state, num_bits[j], value[j]);
} else {
/* program the scan field to 1 bit length, and ignore it's value */
shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0);
}
}
}
static inline void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
int num_fields,
const int *num_bits,
const uint32_t *value,
enum tap_state end_state)
{
int singletap = (jtag_tap_next_enabled(jtag_tap_next_enabled(NULL)) == NULL);
if ((singletap) && (num_fields == 3)) {
/* used by embeddedice_write_reg_inner() */
shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[1], value[1]);
shiftValueInner(TAP_DRSHIFT, end_state, num_bits[2], value[2]);
} else if ((singletap) && (num_fields == 2)) {
/* used by arm7 code */
shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
shiftValueInner(TAP_DRSHIFT, end_state, num_bits[1], value[1]);
} else
interface_jtag_add_dr_out_core(target_tap, num_fields, num_bits, value, end_state);
}
#if BUILD_ZY1000_MASTER
#define interface_jtag_add_callback(callback, in) callback(in)
#define interface_jtag_add_callback4(callback, in, data1, data2, \

View File

@ -631,16 +631,6 @@ static void jtag_pre_post_bits(struct jtag_tap *tap, int *pre, int *post)
*post = post_bits;
}
#if 0
static const int embeddedice_num_bits[] = {32, 6};
uint32_t values[2];
values[0] = value;
values[1] = (1 << 5) | reg_addr;
jtag_add_dr_out(tap, 2, embeddedice_num_bits, values, TAP_IDLE);
#endif
void embeddedice_write_dcc(struct jtag_tap *tap,
int reg_addr,
const uint8_t *buffer,
@ -700,8 +690,7 @@ int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
uint32_t, const uint32_t *, size_t);
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
} else {
static const int bits[] = {32, 2};
uint32_t values[] = {0, 0};
static const uint8_t zero;
/* FIX!!!!!! the target_write_memory() API started this nasty problem
* with unaligned uint32_t * pointers... */
@ -710,7 +699,7 @@ int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
while (--count > 0) {
#if 1
/* Danger! This code doesn't update cmd_queue_cur_state, so
* invoking jtag_add_pathmove() before jtag_add_dr_out() after
* invoking jtag_add_pathmove() before jtag_add_dr_scan() after
* this loop would fail!
*/
shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0);
@ -750,15 +739,15 @@ int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
};
values[0] = *t++;
values[0] |= (*t++<<8);
values[0] |= (*t++<<16);
values[0] |= (*t++<<24);
struct scan_field fields[2] = {
{ .num_bits = 32, .out_value = t },
{ .num_bits = 2, .out_value = &zero },
};
t += 4;
jtag_add_dr_out(tap,
jtag_add_dr_scan(tap,
2,
bits,
values,
fields,
TAP_IDLE);
jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
@ -766,18 +755,17 @@ int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
#endif
}
values[0] = *t++;
values[0] |= (*t++<<8);
values[0] |= (*t++<<16);
values[0] |= (*t++<<24);
struct scan_field fields[2] = {
{ .num_bits = 32, .out_value = t },
{ .num_bits = 2, .out_value = &zero },
};
/* This will happen on the last iteration updating cmd_queue_cur_state
* so we don't have to track it during the common code path
*/
jtag_add_dr_out(tap,
jtag_add_dr_scan(tap,
2,
bits,
values,
fields,
TAP_IDLE);
return jtag_execute_queue();

View File

@ -95,12 +95,18 @@ static const int arm7tdmi_num_bits[] = {1, 32};
static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint)
{
uint32_t values[2] = {breakpoint, flip_u32(out, 32)};
uint8_t bp = breakpoint ? 1 : 0;
uint8_t out_value[4];
buf_set_u32(out_value, 0, 32, flip_u32(out, 32));
jtag_add_dr_out(jtag_info->tap,
struct scan_field fields[2] = {
{ .num_bits = arm7tdmi_num_bits[0], .out_value = &bp },
{ .num_bits = arm7tdmi_num_bits[1], .out_value = out_value },
};
jtag_add_dr_scan(jtag_info->tap,
2,
arm7tdmi_num_bits,
values,
fields,
TAP_DRPAUSE);
jtag_add_runtest(0, TAP_DRPAUSE);

View File

@ -59,20 +59,18 @@ int arm_jtag_set_instr_inner(struct arm_jtag *jtag_info,
int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state)
{
int retval = ERROR_OK;
uint32_t values[1];
int num_bits[1];
values[0] = new_scan_chain;
num_bits[0] = jtag_info->scann_size;
uint8_t out_value[4];
buf_set_u32(out_value, 0, jtag_info->scann_size, new_scan_chain);
struct scan_field field = { .num_bits = jtag_info->scann_size, .out_value = out_value, };
retval = arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL, end_state);
if (retval != ERROR_OK)
return retval;
jtag_add_dr_out(jtag_info->tap,
jtag_add_dr_scan(jtag_info->tap,
1,
num_bits,
values,
&field,
end_state);
jtag_info->cur_scan_chain = new_scan_chain;

View File

@ -112,13 +112,16 @@ int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeou
*/
static inline void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_addr, uint32_t value)
{
static const int embeddedice_num_bits[] = {32, 6};
uint32_t values[2];
uint8_t out_reg_addr = (1 << 5) | reg_addr;
uint8_t out_value[4];
buf_set_u32(out_value, 0, 32, value);
values[0] = value;
values[1] = (1 << 5) | reg_addr;
struct scan_field fields[2] = {
{ .num_bits = 32, .out_value = out_value },
{ .num_bits = 6, .out_value = &out_reg_addr },
};
jtag_add_dr_out(tap, 2, embeddedice_num_bits, values, TAP_IDLE);
jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
}
void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer,

View File

@ -513,8 +513,6 @@ done:
static int xscale_send(struct target *target, const uint8_t *buffer, int count, int size)
{
struct xscale_common *xscale = target_to_xscale(target);
uint32_t t[3];
int bits[3];
int retval;
int done_count = 0;
@ -522,37 +520,45 @@ static int xscale_send(struct target *target, const uint8_t *buffer, int count,
XSCALE_DBGRX << xscale->xscale_variant,
TAP_IDLE);
bits[0] = 3;
t[0] = 0;
bits[1] = 32;
t[2] = 1;
bits[2] = 1;
static const uint8_t t0;
uint8_t t1[4];
static const uint8_t t2 = 1;
struct scan_field fields[3] = {
{ .num_bits = 3, .out_value = &t0 },
{ .num_bits = 32, .out_value = t1 },
{ .num_bits = 1, .out_value = &t2 },
};
int endianness = target->endianness;
while (done_count++ < count) {
uint32_t t;
switch (size) {
case 4:
if (endianness == TARGET_LITTLE_ENDIAN)
t[1] = le_to_h_u32(buffer);
t = le_to_h_u32(buffer);
else
t[1] = be_to_h_u32(buffer);
t = be_to_h_u32(buffer);
break;
case 2:
if (endianness == TARGET_LITTLE_ENDIAN)
t[1] = le_to_h_u16(buffer);
t = le_to_h_u16(buffer);
else
t[1] = be_to_h_u16(buffer);
t = be_to_h_u16(buffer);
break;
case 1:
t[1] = buffer[0];
t = buffer[0];
break;
default:
LOG_ERROR("BUG: size neither 4, 2 nor 1");
return ERROR_COMMAND_SYNTAX_ERROR;
}
jtag_add_dr_out(target->tap,
buf_set_u32(t1, 0, 32, t);
jtag_add_dr_scan(target->tap,
3,
bits,
t,
fields,
TAP_IDLE);
buffer += size;
}