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_INIT(configure.in)
AC_SEARCH_LIBS([ioperm], [ioperm]) AC_SEARCH_LIBS([ioperm], [ioperm])
......
...@@ -30,6 +30,7 @@ This is edition @value{EDITION} of the openocd manual for version ...@@ -30,6 +30,7 @@ This is edition @value{EDITION} of the openocd manual for version
* Configuration:: Openocd Configuration. * Configuration:: Openocd Configuration.
* Commands:: Openocd Commands * Commands:: Openocd Commands
* Sample Scripts:: Sample Target Scripts * Sample Scripts:: Sample Target Scripts
* GDB and Openocd:: Using GDB and Openocd
* FAQ:: Frequently Asked Questions * FAQ:: Frequently Asked Questions
* License:: GNU Free Documentation License * License:: GNU Free Documentation License
* Index:: Main index. * Index:: Main index.
...@@ -194,6 +195,22 @@ Port on which to listen for incoming telnet connections ...@@ -194,6 +195,22 @@ Port on which to listen for incoming telnet connections
@cindex gdb_port @cindex gdb_port
First port on which to listen for incoming GDB connections. The GDB port for the 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. 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} @item @b{daemon_startup} <@var{mode}> either @samp{attach} or @samp{reset}
@cindex daemon_startup @cindex daemon_startup
Tells the OpenOCD whether it should reset the target when the daemon is launched, or 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 ...@@ -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}> @item @b{target_script} <@var{target#}> <@var{event}> <@var{script_file}>
@cindex target_script @cindex target_script
Event is either @var{reset} or @var{post_halt} or @var{pre_resume}. Event is either @option{reset}, @option{post_halt}, @option{pre_resume} or @option{gdb_program_config}
TODO: describe exact semantic of events
TODO: describe exact semantic of events
@item @b{run_and_halt_time} <@var{target#}> <@var{time_in_ms}> @item @b{run_and_halt_time} <@var{target#}> <@var{time_in_ms}>
@cindex run_and_halt_time @cindex run_and_halt_time
The amount of time the debugger should wait after releasing reset before it asserts The amount of time the debugger should wait after releasing reset before it asserts
...@@ -866,8 +884,8 @@ mass erase flash memory. ...@@ -866,8 +884,8 @@ mass erase flash memory.
@end itemize @end itemize
@page @page
@section Arcitecture Specific Commands @section Architecture Specific Commands
@cindex Arcitecture Specific Commands @cindex Architecture Specific Commands
@subsection ARMV4/5 specific commands @subsection ARMV4/5 specific commands
@cindex ARMV4/5 specific commands @cindex ARMV4/5 specific commands
...@@ -1014,7 +1032,7 @@ This page will collect some script examples for different CPUs. ...@@ -1014,7 +1032,7 @@ This page will collect some script examples for different CPUs.
The configuration script can be divided in the following section: The configuration script can be divided in the following section:
@itemize @bullet @itemize @bullet
@item deamon configuration @item daemon configuration
@item interface @item interface
@item jtag scan chain @item jtag scan chain
@item target configuration @item target configuration
...@@ -1025,9 +1043,9 @@ Detailed information about each section can be found at OpenOCD configuration ...@@ -1025,9 +1043,9 @@ Detailed information about each section can be found at OpenOCD configuration
@section OMAP5912 Flash Debug @section OMAP5912 Flash Debug
@cindex OMAP5912 Flash Debug @cindex OMAP5912 Flash Debug
The following two scripts was used with an wiggler PP and and a TI OMAP5912 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 dual core processor - (@uref{http://www.ti.com}), on a OMAP5912 OSK board
(@uref{http://www.spectrumdigital.com}). - (@uref{http://www.spectrumdigital.com}).
@subsection Openocd config @subsection Openocd config
@smallexample @smallexample
#daemon configuration #daemon configuration
...@@ -1280,7 +1298,7 @@ run_and_halt_time 0 30 ...@@ -1280,7 +1298,7 @@ run_and_halt_time 0 30
working_area 0 0x20000000 16384 nobackup working_area 0 0x20000000 16384 nobackup
#flash bank <driver> <base> <size> <chip_width> <bus_width> #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 @end smallexample
@section STM32x Performance Stick @section STM32x Performance Stick
...@@ -1320,7 +1338,7 @@ run_and_halt_time 0 30 ...@@ -1320,7 +1338,7 @@ run_and_halt_time 0 30
working_area 0 0x20000000 16384 nobackup working_area 0 0x20000000 16384 nobackup
#flash bank <driver> <base> <size> <chip_width> <bus_width> #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 @end smallexample
@section LPC2129 Script @section LPC2129 Script
...@@ -1673,6 +1691,71 @@ run_and_halt_time 0 30 ...@@ -1673,6 +1691,71 @@ run_and_halt_time 0 30
flash bank cfi 0x00000000 0x1000000 2 4 0 flash bank cfi 0x00000000 0x1000000 2 4 0
@end smallexample @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 @node FAQ
@chapter FAQ @chapter FAQ
@cindex faq @cindex faq
......
...@@ -393,6 +393,9 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char * ...@@ -393,6 +393,9 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *
return ERROR_INVALID_ARGUMENTS; 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); duration_start_measure(&duration);
if ((retval = flash_erase(target, address, length)) != ERROR_OK) 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 ...@@ -766,6 +769,21 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c
return ERROR_OK; 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 */ /* lookup flash bank by address */
flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr) 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 ...@@ -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 /* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */ * when flash_write is called multiple times */
for (c = flash_banks; c; c = c->next) flash_set_dirty();
{
for (i = 0; i < c->num_sectors; i++)
{
c->sectors[i].is_erased = 0;
}
}
} }
/* loop until we reach end of the image */ /* loop until we reach end of the image */
......
...@@ -68,6 +68,7 @@ extern int flash_init(struct command_context_s *cmd_ctx); ...@@ -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_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 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_num(int num);
extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr); 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) ...@@ -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*/ /* we're inside a word or quote, and reached its end*/
if (word_start) if (word_start)
{ {
int len; int len;
char *word_end=p; char *word_end=p;
/* This will handle extra whitespace within quotes */
while (isspace(*word_start)&&(word_start<word_end)) /* This will handle extra whitespace within quotes */
word_start++; while (isspace(*word_start)&&(word_start<word_end))
while (isspace(*(word_end-1))&&(word_start<word_end)) word_start++;
word_end--; while (isspace(*(word_end-1))&&(word_start<word_end))
word_end--;
len = word_end - word_start; len = word_end - word_start;
if (len>0) if (len>0)
{ {
/* copy the word */ /* copy the word */
memcpy(words[nwords] = malloc(len + 1), word_start, len); memcpy(words[nwords] = malloc(len + 1), word_start, len);
/* add terminating NUL */ /* add terminating NUL */
words[nwords++][len] = 0; words[nwords++][len] = 0;
} }
} }
/* we're done parsing the line */ /* we're done parsing the line */
if (!*p) if (!*p)
break; break;
...@@ -226,9 +225,9 @@ int parse_line(char *line, char *words[], int max_words) ...@@ -226,9 +225,9 @@ int parse_line(char *line, char *words[], int max_words)
/* skip over trailing quote or whitespace*/ /* skip over trailing quote or whitespace*/
if (inquote || isspace(*p)) if (inquote || isspace(*p))
p++; p++;
while (isspace(*p)) while (isspace(*p))
p++; p++;
inquote = 0; inquote = 0;
word_start = 0; word_start = 0;
} }
...@@ -267,14 +266,23 @@ void command_print(command_context_t *context, char *format, ...) ...@@ -267,14 +266,23 @@ void command_print(command_context_t *context, char *format, ...)
{ {
/* increase buffer until it fits the whole string */ /* increase buffer until it fits the whole string */
if (!(p = realloc(buffer, size += 4096))) if (!(p = realloc(buffer, size += 4096)))
{
/* gotta free up */
if (buffer)
free(buffer);
return; return;
}
buffer = p; buffer = p;
} }
/* vsnprintf failed */ /* vsnprintf failed */
if (n < 0) if (n < 0)
{
if (buffer)
free(buffer);
return; return;
}
p = buffer; p = buffer;
......
This diff is collapsed.
INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/target -I$(top_srcdir)/src/flash $(all_includes) INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/target -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/jtag $(all_includes)
METASOURCES = AUTO METASOURCES = AUTO
noinst_LIBRARIES = libserver.a noinst_LIBRARIES = libserver.a
noinst_HEADERS = server.h telnet_server.h gdb_server.h noinst_HEADERS = server.h telnet_server.h gdb_server.h
......
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
#include "server.h" #include "server.h"
#include "log.h" #include "log.h"
#include "binarybuffer.h" #include "binarybuffer.h"
#include "jtag.h"
#include "breakpoints.h" #include "breakpoints.h"
#include "flash.h" #include "flash.h"
#include "target_request.h" #include "target_request.h"
#define __USE_GNU
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
...@@ -52,8 +52,14 @@ enum gdb_detach_mode ...@@ -52,8 +52,14 @@ enum gdb_detach_mode
GDB_DETACH_NOTHING GDB_DETACH_NOTHING
}; };
/* target behaviour on gdb detach */
enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME; enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
/* set if we are sending a memory map to gdb
* via qXfer:memory-map:read packet */
int gdb_use_memory_map = 0;
int gdb_flash_program = 0;
int gdb_last_signal(target_t *target) int gdb_last_signal(target_t *target)
{ {
switch (target->debug_reason) switch (target->debug_reason)
...@@ -77,7 +83,10 @@ int gdb_last_signal(target_t *target) ...@@ -77,7 +83,10 @@ int gdb_last_signal(target_t *target)
int gdb_get_char(connection_t *connection, int* next_char) int gdb_get_char(connection_t *connection, int* next_char)
{ {
gdb_connection_t *gdb_con = connection->priv; gdb_connection_t *gdb_con = connection->priv;
#ifdef _DEBUG_GDB_IO_
char *debug_buffer; char *debug_buffer;
#endif
if (gdb_con->buf_cnt-- > 0) if (gdb_con->buf_cnt-- > 0)
{ {
...@@ -109,6 +118,8 @@ int gdb_get_char(connection_t *connection, int* next_char) ...@@ -109,6 +118,8 @@ int gdb_get_char(connection_t *connection, int* next_char)
break; break;
case WSAECONNABORTED: case WSAECONNABORTED:
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
case WSAECONNRESET:
return ERROR_SERVER_REMOTE_CLOSED;
default: default:
ERROR("read: %d", errno); ERROR("read: %d", errno);
exit(-1); exit(-1);
...@@ -130,11 +141,13 @@ int gdb_get_char(connection_t *connection, int* next_char) ...@@ -130,11 +141,13 @@ int gdb_get_char(connection_t *connection, int* next_char)
#endif #endif
} }
#ifdef _DEBUG_GDB_IO_
debug_buffer = malloc(gdb_con->buf_cnt + 1); debug_buffer = malloc(gdb_con->buf_cnt + 1);
memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt); memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
debug_buffer[gdb_con->buf_cnt] = 0; debug_buffer[gdb_con->buf_cnt] = 0;
DEBUG("received '%s'", debug_buffer); DEBUG("received '%s'", debug_buffer);
free(debug_buffer); free(debug_buffer);
#endif
gdb_con->buf_p = gdb_con->buffer; gdb_con->buf_p = gdb_con->buffer;
gdb_con->buf_cnt--; gdb_con->buf_cnt--;
...@@ -245,7 +258,9 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) ...@@ -245,7 +258,9 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval; return retval;
#ifdef _DEBUG_GDB_IO_
DEBUG("character: '%c'", character); DEBUG("character: '%c'", character);
#endif
switch (character) switch (character)
{ {
...@@ -325,9 +340,17 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) ...@@ -325,9 +340,17 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
int gdb_output(struct command_context_s *context, char* line) int gdb_output(struct command_context_s *context, char* line)
{ {
connection_t *connection = context->output_handler_priv; connection_t *connection = context->output_handler_priv;
gdb_connection_t *gdb_connection = connection->priv;
char *hex_buffer; char *hex_buffer;
int i, bin_size; int i, bin_size;
/* check if output is enabled */
if (gdb_connection->output_disable)
{
return ERROR_OK;
}
bin_size = strlen(line); bin_size = strlen(line);
hex_buffer = malloc(bin_size*2 + 4); hex_buffer = malloc(bin_size*2 + 4);
...@@ -345,6 +368,30 @@ int gdb_output(struct command_context_s *context, char* line) ...@@ -345,6 +368,30 @@ int gdb_output(struct command_context_s *context, char* line)
return ERROR_OK; return ERROR_OK;
} }
int gdb_program_handler(struct target_s *target, enum target_event event, void *priv)
{
FILE *script;
struct command_context_s *cmd_ctx = priv;
if (target->gdb_program_script)
{
script = fopen(target->gdb_program_script, "r");
if (!script)
{
ERROR("couldn't open script file %s", target->gdb_program_script);
return ERROR_OK;
}
INFO("executing gdb_program script '%s'", target->gdb_program_script);
command_run_file(cmd_ctx, script, COMMAND_EXEC);
fclose(script);
jtag_execute_queue();
}
return ERROR_OK;
}
int gdb_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv) int gdb_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)
{ {
connection_t *connection = priv; connection_t *connection = priv;
...@@ -378,6 +425,9 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event ...@@ -378,6 +425,9 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
gdb_connection->frontend_state = TARGET_RUNNING; gdb_connection->frontend_state = TARGET_RUNNING;
} }
break; break;
case TARGET_EVENT_GDB_PROGRAM:
gdb_program_handler(target, event, connection->cmd_ctx);
break;
default: default:
break; break;
} }
...@@ -400,7 +450,8 @@ int gdb_new_connection(connection_t *connection) ...@@ -400,7 +450,8 @@ int gdb_new_connection(connection_t *connection)
gdb_connection->ctrl_c = 0; gdb_connection->ctrl_c = 0;
gdb_connection->frontend_state = TARGET_HALTED; gdb_connection->frontend_state = TARGET_HALTED;
gdb_connection->vflash_image = NULL; gdb_connection->vflash_image = NULL;
gdb_connection->output_disable = 0;
/* output goes through gdb connection */ /* output goes through gdb connection */
command_set_output_handler(connection->cmd_ctx, gdb_output, connection); command_set_output_handler(connection->cmd_ctx, gdb_output, connection);
...@@ -1172,10 +1223,76 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, ...@@ -1172,10 +1223,76 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
return ERROR_OK; return ERROR_OK;
} }
/* print out XML and allocate more space as needed */
void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...)
{
if (*retval != ERROR_OK)
{
return;
}
int first = 1;
for (;;)
{
if ((*xml == NULL) || (!first))
{
/* start by 0 to exercise all the code paths.
* Need minimum 2 bytes to fit 1 char and 0 terminator. */
*size = *size * 2 + 2;
*xml = realloc(*xml, *size);
if (*xml == NULL)
{
*retval = 1;
return;
}
}
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(*xml + *pos, *size - *pos, fmt, ap);
va_end(ap);
if ((ret > 0) && ((ret + 1) < *size - *pos))