Commit 6c9b804d authored by ntfreak's avatar ntfreak
Browse files

- minimum autoconf 2.59 is now required and verified - due to issues with AS_HELP_STRING

- native win32 now handles WSAECONNRESET - no longer exits openocd
- qCRC packet now works correctly under cygwin (gdb compare-sections command)
- removed __USE_GNU define from gdbserver.c
- gdb qSupported packet is now handled, with this we are able to tell gdb packet size, memory map of target
- added new target script gdb_program_config - called before gdb flash programming
- new gdb server command gdb_memory_map (enable|disable> - default is disable
- new gdb server command gdb_flash_program (enable|disable> - default is disable
- gdb flash programming supported - vFlash packets
- image_elf_read_section now does not clear any remaining data, this was causing the gdb checksum to fail with certain files
- reformat of usbprog.c
- memory leak in command_print fixed
- updated texi doc to include new commands
- added gdb programming section to docs

git-svn-id: svn://svn.berlios.de/openocd/trunk@246 b42882b7-edfa-0310-969c-e2dbd0fdcd60
parent 2ec5bd28
AC_PREREQ(2.59)
AC_INIT(configure.in)
AC_SEARCH_LIBS([ioperm], [ioperm])
......
......@@ -30,6 +30,7 @@ This is edition @value{EDITION} of the openocd manual for version
* Configuration:: Openocd Configuration.
* Commands:: Openocd Commands
* Sample Scripts:: Sample Target Scripts
* GDB and Openocd:: Using GDB and Openocd
* FAQ:: Frequently Asked Questions
* License:: GNU Free Documentation License
* Index:: Main index.
......@@ -194,6 +195,22 @@ Port on which to listen for incoming telnet connections
@cindex gdb_port
First port on which to listen for incoming GDB connections. The GDB port for the
first target will be gdb_port, the second target will listen on gdb_port + 1, and so on.
@item @b{gdb_detach} <@var{resume|reset|halt|nothing}>
@cindex gdb_detach
Configures what openocd will do when gdb detaches from the daeman.
Default behaviour is <@var{resume}>
@item @b{gdb_memory_map} <@var{enable|disable}>
@cindex gdb_memory_map
Set to <@var{enable}> so that openocd will send the memory configuration to gdb when
requested. gdb will then know when to set hardware breakpoints, and program flash
using the gdb load command. @option{gdb_flash_program enable} will also need enabling
for flash programming to work.
Default behaviour is <@var{disable}>
@item @b{gdb_flash_program} <@var{enable|disable}>
@cindex gdb_flash_program
Set to <@var{enable}> so that openocd will program the flash memory when a
vFlash packet is received.
Default behaviour is <@var{disable}>
@item @b{daemon_startup} <@var{mode}> either @samp{attach} or @samp{reset}
@cindex daemon_startup
Tells the OpenOCD whether it should reset the target when the daemon is launched, or
......@@ -441,8 +458,9 @@ unavailable for some time during startup (like the STR7 series), you can't use
@item @b{target_script} <@var{target#}> <@var{event}> <@var{script_file}>
@cindex target_script
Event is either @var{reset} or @var{post_halt} or @var{pre_resume}.
TODO: describe exact semantic of events
Event is either @option{reset}, @option{post_halt}, @option{pre_resume} or @option{gdb_program_config}
TODO: describe exact semantic of events
@item @b{run_and_halt_time} <@var{target#}> <@var{time_in_ms}>
@cindex run_and_halt_time
The amount of time the debugger should wait after releasing reset before it asserts
......@@ -866,8 +884,8 @@ mass erase flash memory.
@end itemize
@page
@section Arcitecture Specific Commands
@cindex Arcitecture Specific Commands
@section Architecture Specific Commands
@cindex Architecture Specific Commands
@subsection ARMV4/5 specific commands
@cindex ARMV4/5 specific commands
......@@ -1014,7 +1032,7 @@ This page will collect some script examples for different CPUs.
The configuration script can be divided in the following section:
@itemize @bullet
@item deamon configuration
@item daemon configuration
@item interface
@item jtag scan chain
@item target configuration
......@@ -1025,9 +1043,9 @@ Detailed information about each section can be found at OpenOCD configuration
@section OMAP5912 Flash Debug
@cindex OMAP5912 Flash Debug
The following two scripts was used with an wiggler PP and and a TI OMAP5912
dual core processor (@uref{http://www.ti.com}) on a OMAP5912 OSK board
(@uref{http://www.spectrumdigital.com}).
The following two scripts were used with a wiggler PP and and a TI OMAP5912
dual core processor - (@uref{http://www.ti.com}), on a OMAP5912 OSK board
- (@uref{http://www.spectrumdigital.com}).
@subsection Openocd config
@smallexample
#daemon configuration
......@@ -1280,7 +1298,7 @@ run_and_halt_time 0 30
working_area 0 0x20000000 16384 nobackup
#flash bank <driver> <base> <size> <chip_width> <bus_width>
flash bank stm32x 0x08000000 0x00010000 0 0 0
flash bank stm32x 0x08000000 0x00020000 0 0 0
@end smallexample
@section STM32x Performance Stick
......@@ -1320,7 +1338,7 @@ run_and_halt_time 0 30
working_area 0 0x20000000 16384 nobackup
#flash bank <driver> <base> <size> <chip_width> <bus_width>
flash bank stm32x 0x08000000 0x00010000 0 0 0
flash bank stm32x 0x08000000 0x00020000 0 0 0
@end smallexample
@section LPC2129 Script
......@@ -1673,6 +1691,71 @@ run_and_halt_time 0 30
flash bank cfi 0x00000000 0x1000000 2 4 0
@end smallexample
@node GDB and Openocd
@chapter GDB and Openocd
@cindex GDB and Openocd
Openocd complies with the remote gdbserver protocol, and as such can be used
to debug remote targets.
@section Connecting to gdb
@cindex Connecting to gdb
A connection is typically started as follows:
@smallexample
target remote localhost:3333
@end smallexample
This would cause gdb to connect to the gdbserver on the local pc using port 3333.
To see a list of available openocd commands type @option{monitor help} on the
gdb commandline.
Openocd supports the gdb @option{qSupported} packet, this enables information
to be sent by the gdb server (openocd) to gdb. Typical information includes
packet size and device memory map.
Previous versions of openocd required the following gdb options to increase
the packet size and speed up gdb communication.
@smallexample
set remote memory-write-packet-size 1024
set remote memory-write-packet-size fixed
set remote memory-read-packet-size 1024
set remote memory-read-packet-size fixed
@end smallexample
This is now handled in the @option{qSupported} PacketSize.
@section Programming using gdb
@cindex Programming using gdb
By default the target memory map is not sent to gdb, this can be enabled by
the following openocd config option:
@smallexample
gdb_memory_map enable
@end smallexample
For this to function correctly a valid flash config must also be configured
in openocd. For speed also configure a valid working area.
Informing gdb of the memory map of the target will enable gdb to protect any
flash area of the target and use hardware breakpoints by default. This means
that the openocd option @option{arm7_9 force_hw_bkpts} is not required when
using a memory map.
To view the configured memory map in gdb, use the gdb command @option{info mem}
All other unasigned addresses within gdb are treated as ram.
If @option{gdb_flash_program enable} is also used, gdb will be able to
program any flash memory using the vFlash interface.
gdb will look at the target memory map when a load command is given, if any
areas to be programmed lie within the target flash area the vFlash packets
will be used.
Incase the target needs configuring before gdb programming, a script can be executed.
@smallexample
target_script 0 gdb_program_config config.script
@end smallexample
To verify any flash programming the gdb command @option{compare-sections}
can be used.
@node FAQ
@chapter FAQ
@cindex faq
......
......@@ -393,6 +393,9 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *
return ERROR_INVALID_ARGUMENTS;
}
/* We can't know if we did a resume + halt, in which case we no longer know the erased state */
flash_set_dirty();
duration_start_measure(&duration);
if ((retval = flash_erase(target, address, length)) != ERROR_OK)
......@@ -766,6 +769,21 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c
return ERROR_OK;
}
void flash_set_dirty(void)
{
flash_bank_t *c;
int i;
/* set all flash to require erasing */
for (c = flash_banks; c; c = c->next)
{
for (i = 0; i < c->num_sectors; i++)
{
c->sectors[i].is_erased = 0;
}
}
}
/* lookup flash bank by address */
flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr)
{
......@@ -852,14 +870,8 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str
{
/* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */
for (c = flash_banks; c; c = c->next)
{
for (i = 0; i < c->num_sectors; i++)
{
c->sectors[i].is_erased = 0;
}
}
flash_set_dirty();
}
/* loop until we reach end of the image */
......
......@@ -68,6 +68,7 @@ extern int flash_init(struct command_context_s *cmd_ctx);
extern int flash_erase(target_t *target, u32 addr, u32 length);
extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed, int erase);
extern void flash_set_dirty(void);
extern flash_bank_t *get_flash_bank_by_num(int num);
extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
......
......@@ -200,25 +200,24 @@ int parse_line(char *line, char *words[], int max_words)
/* we're inside a word or quote, and reached its end*/
if (word_start)
{
int len;
char *word_end=p;
/* This will handle extra whitespace within quotes */
while (isspace(*word_start)&&(word_start<word_end))
word_start++;
while (isspace(*(word_end-1))&&(word_start<word_end))
word_end--;
len = word_end - word_start;
if (len>0)
{
/* copy the word */
memcpy(words[nwords] = malloc(len + 1), word_start, len);
/* add terminating NUL */
words[nwords++][len] = 0;
}
int len;
char *word_end=p;
/* This will handle extra whitespace within quotes */
while (isspace(*word_start)&&(word_start<word_end))
word_start++;
while (isspace(*(word_end-1))&&(word_start<word_end))
word_end--;
len = word_end - word_start;
if (len>0)
{
/* copy the word */
memcpy(words[nwords] = malloc(len + 1), word_start, len);
/* add terminating NUL */
words[nwords++][len] = 0;
}
}
/* we're done parsing the line */
if (!*p)
break;
......@@ -226,9 +225,9 @@ int parse_line(char *line, char *words[], int max_words)
/* skip over trailing quote or whitespace*/
if (inquote || isspace(*p))
p++;
while (isspace(*p))
p++;
while (isspace(*p))
p++;
inquote = 0;
word_start = 0;
}
......@@ -267,14 +266,23 @@ void command_print(command_context_t *context, char *format, ...)
{
/* increase buffer until it fits the whole string */
if (!(p = realloc(buffer, size += 4096)))
{
/* gotta free up */
if (buffer)
free(buffer);
return;
}
buffer = p;
}
/* vsnprintf failed */
if (n < 0)
{
if (buffer)
free(buffer);
return;
}
p = buffer;
......
/***************************************************************************
* Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de *
* based on Dominic Rath's amt_jtagaccel.c *
* *
* usbprog is a free programming adapter. You can easily install *
* different firmware versions from an "online pool" over USB. *
* The adapter can be used for programming and debugging AVR and ARM *
* processors, as USB to RS232 converter, as JTAG interface or as *
* simple I/O interface (5 lines). *
* *
* http://www.embedded-projects.net/usbprog *
* Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de *
* based on Dominic Rath's amt_jtagaccel.c *
* *
* usbprog is a free programming adapter. You can easily install *
* different firmware versions from an "online pool" over USB. *
* The adapter can be used for programming and debugging AVR and ARM *
* processors, as USB to RS232 converter, as JTAG interface or as *
* simple I/O interface (5 lines). *
* *
* http://www.embedded-projects.net/usbprog *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
......@@ -42,7 +42,7 @@
#define VID 0x1781
#define PID 0x0c63
// Pins at usbprog
/* Pins at usbprog */
#define TDO_BIT 0
#define TDI_BIT 3
#define TCK_BIT 2
......@@ -54,7 +54,6 @@ int usbprog_register_commands(struct command_context_s *cmd_ctx);
int usbprog_init(void);
int usbprog_quit(void);
void usbprog_end_state(enum tap_state state);
void usbprog_state_move(void);
void usbprog_path_move(pathmove_command_t *cmd);
......@@ -96,7 +95,6 @@ void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);
void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
......@@ -126,111 +124,110 @@ int usbprog_register_commands(struct command_context_s *cmd_ctx)
return ERROR_OK;
}
int usbprog_execute_queue(void)
{
jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
int scan_size;
enum scan_type type;
u8 *buffer;
while (cmd)
{
switch (cmd->type)
{
case JTAG_END_STATE:
jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
int scan_size;
enum scan_type type;
u8 *buffer;
while (cmd)
{
switch (cmd->type)
{
case JTAG_END_STATE:
#ifdef _DEBUG_JTAG_IO_
DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
#endif
if (cmd->cmd.end_state->end_state != -1)
usbprog_end_state(cmd->cmd.end_state->end_state);
break;
case JTAG_RESET:
if (cmd->cmd.end_state->end_state != -1)
usbprog_end_state(cmd->cmd.end_state->end_state);
break;
case JTAG_RESET:
#ifdef _DEBUG_JTAG_IO_
DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
#endif
if (cmd->cmd.reset->trst == 1)
{
cur_state = TAP_TLR;
}
usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
case JTAG_RUNTEST:
if (cmd->cmd.reset->trst == 1)
{
cur_state = TAP_TLR;
}
usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
case JTAG_RUNTEST:
#ifdef _DEBUG_JTAG_IO_
DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
#endif
if (cmd->cmd.runtest->end_state != -1)
usbprog_end_state(cmd->cmd.runtest->end_state);
usbprog_runtest(cmd->cmd.runtest->num_cycles);
break;
case JTAG_STATEMOVE:
if (cmd->cmd.runtest->end_state != -1)
usbprog_end_state(cmd->cmd.runtest->end_state);
usbprog_runtest(cmd->cmd.runtest->num_cycles);
break;
case JTAG_STATEMOVE:
#ifdef _DEBUG_JTAG_IO_
DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
#endif
if (cmd->cmd.statemove->end_state != -1)
usbprog_end_state(cmd->cmd.statemove->end_state);
usbprog_state_move();
break;
case JTAG_PATHMOVE:
if (cmd->cmd.statemove->end_state != -1)
usbprog_end_state(cmd->cmd.statemove->end_state);
usbprog_state_move();
break;
case JTAG_PATHMOVE:
#ifdef _DEBUG_JTAG_IO_
DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
#endif
usbprog_path_move(cmd->cmd.pathmove);
break;
case JTAG_SCAN:
usbprog_path_move(cmd->cmd.pathmove);
break;
case JTAG_SCAN:
#ifdef _DEBUG_JTAG_IO_
DEBUG("scan end in %i", cmd->cmd.scan->end_state);
DEBUG("scan end in %i", cmd->cmd.scan->end_state);
#endif
if (cmd->cmd.scan->end_state != -1)
usbprog_end_state(cmd->cmd.scan->end_state);
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
type = jtag_scan_type(cmd->cmd.scan);
usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
return ERROR_JTAG_QUEUE_FAILED;
if (buffer)
free(buffer);
break;
case JTAG_SLEEP:
if (cmd->cmd.scan->end_state != -1)
usbprog_end_state(cmd->cmd.scan->end_state);
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
type = jtag_scan_type(cmd->cmd.scan);
usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
return ERROR_JTAG_QUEUE_FAILED;
if (buffer)
free(buffer);
break;
case JTAG_SLEEP:
#ifdef _DEBUG_JTAG_IO_
DEBUG("sleep %i", cmd->cmd.sleep->us);
DEBUG("sleep %i", cmd->cmd.sleep->us);
#endif
jtag_sleep(cmd->cmd.sleep->us);
break;
default:
ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
}
cmd = cmd->next;
}
return ERROR_OK;
jtag_sleep(cmd->cmd.sleep->us);
break;
default:
ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
}
cmd = cmd->next;
}
return ERROR_OK;
}
int usbprog_init(void)
{
usbprog_jtag_handle = usbprog_jtag_open();
tms_chain_index=0;
if(usbprog_jtag_handle==0){
tms_chain_index = 0;
if (usbprog_jtag_handle == 0)
{
ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}
INFO("USB JTAG Interface ready!");
usbprog_jtag_init(usbprog_jtag_handle);
usbprog_reset(0, 0);
usbprog_write(0, 0, 0);
return ERROR_OK;
}
int usbprog_quit(void)
{
return ERROR_OK;
}
......@@ -246,200 +243,194 @@ void usbprog_end_state(enum tap_state state)
}
}
void usbprog_state_move(void) {
int i=0, tms=0;
u8 tms_scan = TAP_MOVE(cur_state, end_state);
usbprog_jtag_write_tms(usbprog_jtag_handle,(char)tms_scan);
for (i = 0; i < 7; i++)
{
tms = (tms_scan >> i) & 1;
}
void usbprog_state_move(void)
{
int i = 0, tms = 0;
u8 tms_scan = TAP_MOVE(cur_state, end_state);
cur_state = end_state;
usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
for (i = 0; i < 7; i++)
{
tms = (tms_scan >> i) & 1;
}
cur_state = end_state;
}
void usbprog_path_move(pathmove_command_t *cmd)
{
int num_states = cmd->num_states;
int state_count;
state_count = 0;
while (num_states)
{
if (tap_transitions[cur_state].low == cmd->path[state_count])
{
int num_states = cmd->num_states;
int state_count;
state_count = 0;
while (num_states)
{
if (tap_transitions[cur_state].low == cmd->path[state_count])
{
//INFO("1");
usbprog_write(0, 0, 0);
usbprog_write(1, 0, 0);
}
else if (tap_transitions[cur_state].high == cmd->path[state_count])
{
usbprog_write(0, 0, 0);
usbprog_write(1, 0, 0);
}
else if (tap_transitions[cur_state].high == cmd->path[state_count])
{
//INFO("2");
usbprog_write(0, 1, 0);
usbprog_write(1, 1, 0);
}
else
{
ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
exit(-1);
}
cur_state = cmd->path[state_count];
state_count++;
num_states--;
}
end_state = cur_state;
usbprog_write(0, 1, 0);
usbprog_write(1, 1, 0);
}
else
{
ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
exit(-1);
}