- the jtag chain is examined and validated after GDB & telnet servers
are up and running. The examination and validation is actually "optional" from the point of view of GDB + telnet servers. Multiple targets should work fine with this. - jtag_speed is dropped(divisor is increased), if jtag examination and validation fails. - the chain is validated 10x to catch the worst jtag_speed offences - added LOG_SILENT that can be used to shut up log. Feeble ersatz for try+catch. - GDB register packets are now always replied in order to make sure that GDB connect works. If the target is not halted, then these packets contain dummy values. git-svn-id: svn://svn.berlios.de/openocd/trunk@483 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
parent
0424155dfc
commit
e6dac739cf
|
@ -9,7 +9,7 @@ else
|
||||||
FTD2XXINC =
|
FTD2XXINC =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/helper $(FTD2XXINC) $(all_includes)
|
INCLUDES = -I$(top_srcdir)/src/helper $(FTD2XXINC) $(all_includes) -I$(top_srcdir)/src/target
|
||||||
METASOURCES = AUTO
|
METASOURCES = AUTO
|
||||||
noinst_LIBRARIES = libjtag.a
|
noinst_LIBRARIES = libjtag.a
|
||||||
|
|
||||||
|
|
122
src/jtag/jtag.c
122
src/jtag/jtag.c
|
@ -28,6 +28,7 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
@ -1327,11 +1328,10 @@ void jtag_sleep(u32 us)
|
||||||
|
|
||||||
/* Try to examine chain layout according to IEEE 1149.1 §12
|
/* Try to examine chain layout according to IEEE 1149.1 §12
|
||||||
*/
|
*/
|
||||||
int jtag_examine_chain()
|
int jtag_examine_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4] )
|
||||||
{
|
{
|
||||||
jtag_device_t *device = jtag_devices;
|
jtag_device_t *device = jtag_devices;
|
||||||
scan_field_t field;
|
scan_field_t field;
|
||||||
u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
|
|
||||||
int i;
|
int i;
|
||||||
int bit_count;
|
int bit_count;
|
||||||
int device_count = 0;
|
int device_count = 0;
|
||||||
|
@ -1533,9 +1533,36 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int jtag_init_chain(struct command_context_s *cmd_ctx);
|
||||||
|
|
||||||
|
static int jtag_sense_handler(void *priv)
|
||||||
|
{
|
||||||
|
struct command_context_s *cmd_ctx;
|
||||||
|
cmd_ctx=(struct command_context_s *)priv;
|
||||||
|
|
||||||
|
static int scan_complete = 0;
|
||||||
|
if (!scan_complete)
|
||||||
|
{
|
||||||
|
if (jtag_init_chain(cmd_ctx)==ERROR_OK)
|
||||||
|
{
|
||||||
|
scan_complete = 1;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OpenOCD will start telnet/gdb servers before the JTAG chain has
|
||||||
|
* been enumerated. This is to allow e.g. GDB init script to
|
||||||
|
* run monitor commands to initialize the target so jtag_init_chain()
|
||||||
|
* will succeed.
|
||||||
|
*
|
||||||
|
* A timer callback is added where sensing is retried once every second
|
||||||
|
* until it succeeds.
|
||||||
|
*/
|
||||||
int jtag_init(struct command_context_s *cmd_ctx)
|
int jtag_init(struct command_context_s *cmd_ctx)
|
||||||
{
|
{
|
||||||
int validate_tries = 0;
|
|
||||||
jtag_device_t *device;
|
jtag_device_t *device;
|
||||||
|
|
||||||
DEBUG("-");
|
DEBUG("-");
|
||||||
|
@ -1556,26 +1583,78 @@ int jtag_init(struct command_context_s *cmd_ctx)
|
||||||
jtag_add_statemove(TAP_TLR);
|
jtag_add_statemove(TAP_TLR);
|
||||||
jtag_execute_queue();
|
jtag_execute_queue();
|
||||||
|
|
||||||
/* examine chain first, as this could discover the real chain layout */
|
target_register_timer_callback(jtag_sense_handler, 1000, 1, cmd_ctx);
|
||||||
if (jtag_examine_chain() != ERROR_OK)
|
|
||||||
{
|
|
||||||
ERROR("trying to validate configured JTAG chain anyway...");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (jtag_validate_chain() != ERROR_OK)
|
|
||||||
{
|
|
||||||
validate_tries++;
|
|
||||||
if (validate_tries > 5)
|
|
||||||
{
|
|
||||||
ERROR("Could not validate JTAG chain, exit");
|
|
||||||
return ERROR_JTAG_INVALID_INTERFACE;
|
|
||||||
}
|
|
||||||
usleep(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jtag_test_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4])
|
||||||
|
{
|
||||||
|
jtag_add_statemove(TAP_TLR);
|
||||||
|
jtag_execute_queue();
|
||||||
|
|
||||||
|
/* examine chain first, as this could discover the real chain layout */
|
||||||
|
if (jtag_examine_chain(idcode_buffer)!=ERROR_OK)
|
||||||
|
{
|
||||||
|
WARNING("trying to validate configured JTAG chain anyway...");
|
||||||
|
}
|
||||||
|
|
||||||
|
return jtag_validate_chain();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unless we can do this successfully 10 times, we're not
|
||||||
|
* satisfied with the quality of the JTAG communication.
|
||||||
|
*
|
||||||
|
* Since we're continously repeating this operation, be a bit
|
||||||
|
* wary of filling the log with megabytes of data.
|
||||||
|
*
|
||||||
|
* Keep increasing the jtag_divisor until we've got a solid
|
||||||
|
* result.
|
||||||
|
*/
|
||||||
|
int jtag_init_chain(struct command_context_s *cmd_ctx)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int retval;
|
||||||
|
for (i=jtag_speed; i<64; i++)
|
||||||
|
{
|
||||||
|
u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
|
||||||
|
jtag_speed=i;
|
||||||
|
if ((retval=jtag->speed(jtag_speed))!=ERROR_OK)
|
||||||
|
continue;
|
||||||
|
for (j=0; j<10; j++)
|
||||||
|
{
|
||||||
|
u8 idcode_current[JTAG_MAX_CHAIN_SIZE * 4];
|
||||||
|
enum log_levels save_log_level=debug_level;
|
||||||
|
/* avoid spamming log */
|
||||||
|
debug_level=LOG_SILENT;
|
||||||
|
retval=jtag_test_chain(idcode_current);
|
||||||
|
if (retval==ERROR_OK)
|
||||||
|
{
|
||||||
|
if (j==0)
|
||||||
|
{
|
||||||
|
memcpy(idcode_buffer, idcode_current, sizeof(idcode_buffer));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
retval=(memcmp(idcode_buffer, idcode_current, sizeof(idcode_buffer))==0)?ERROR_OK:ERROR_JTAG_INIT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_level = save_log_level;
|
||||||
|
if (retval!=ERROR_OK)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retval==ERROR_OK)
|
||||||
|
{
|
||||||
|
/* Print out result */
|
||||||
|
INFO("Succeeded jtag chain test jtag_speed=%d", jtag_speed);
|
||||||
|
return jtag_test_chain(idcode_buffer);
|
||||||
|
}
|
||||||
|
DEBUG("Failed jtag chain test, dropping clock rate. Trying jtag_speed=%d\n", i+1);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1778,12 +1857,11 @@ int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
|
|
||||||
if (argc > 0)
|
if (argc > 0)
|
||||||
{
|
{
|
||||||
|
jtag_speed = strtoul(args[0], NULL, 0);
|
||||||
/* this command can be called during CONFIG,
|
/* this command can be called during CONFIG,
|
||||||
* in which case jtag isn't initialized */
|
* in which case jtag isn't initialized */
|
||||||
if (jtag)
|
if (jtag)
|
||||||
jtag->speed(strtoul(args[0], NULL, 0));
|
jtag->speed(jtag_speed);
|
||||||
else
|
|
||||||
jtag_speed = strtoul(args[0], NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -1040,12 +1040,6 @@ int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], i
|
||||||
|
|
||||||
arm11_common_t * arm11 = target->arch_info;
|
arm11_common_t * arm11 = target->arch_info;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
WARNING("target was not halted");
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reg_list_size = ARM11_GDB_REGISTER_COUNT;
|
*reg_list_size = ARM11_GDB_REGISTER_COUNT;
|
||||||
*reg_list = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
|
*reg_list = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
|
||||||
|
|
||||||
|
|
|
@ -474,12 +474,6 @@ int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list
|
||||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
ERROR("Target not halted");
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reg_list_size = 26;
|
*reg_list_size = 26;
|
||||||
*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
|
||||||
|
|
||||||
|
|
|
@ -321,12 +321,6 @@ int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_
|
||||||
armv7m_common_t *armv7m = target->arch_info;
|
armv7m_common_t *armv7m = target->arch_info;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
ERROR("Target not halted");
|
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reg_list_size = 26;
|
*reg_list_size = 26;
|
||||||
*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
|
*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,15 @@ typedef struct target_type_s
|
||||||
int (*soft_reset_halt)(struct target_s *target);
|
int (*soft_reset_halt)(struct target_s *target);
|
||||||
int (*prepare_reset_halt)(struct target_s *target);
|
int (*prepare_reset_halt)(struct target_s *target);
|
||||||
|
|
||||||
/* target register access for gdb */
|
/* target register access for gdb.
|
||||||
|
*
|
||||||
|
* Danger! this function will succeed even if the target is running
|
||||||
|
* and return a register list with dummy values.
|
||||||
|
*
|
||||||
|
* The reason is that GDB connection will fail without a valid register
|
||||||
|
* list, however it is after GDB is connected that monitor commands can
|
||||||
|
* be run to properly initialize the target
|
||||||
|
*/
|
||||||
int (*get_gdb_reg_list)(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
|
int (*get_gdb_reg_list)(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
|
||||||
|
|
||||||
/* target memory access
|
/* target memory access
|
||||||
|
|
Loading…
Reference in New Issue