Browse Source

- 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
tags/v0.1.0
ntfreak 16 years ago
parent
commit
6c9b804d61
12 changed files with 791 additions and 373 deletions
  1. +1
    -0
      configure.in
  2. +93
    -10
      doc/openocd.texi
  3. +20
    -8
      src/flash/flash.c
  4. +1
    -0
      src/flash/flash.h
  5. +29
    -21
      src/helper/command.c
  6. +302
    -296
      src/jtag/usbprog.c
  7. +1
    -1
      src/server/Makefile.am
  8. +318
    -12
      src/server/gdb_server.c
  9. +1
    -0
      src/server/gdb_server.h
  10. +16
    -25
      src/target/image.c
  11. +7
    -0
      src/target/target.c
  12. +2
    -0
      src/target/target.h

+ 1
- 0
configure.in View File

@@ -1,3 +1,4 @@
AC_PREREQ(2.59)
AC_INIT(configure.in)

AC_SEARCH_LIBS([ioperm], [ioperm])


+ 93
- 10
doc/openocd.texi View File

@@ -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


+ 20
- 8
src/flash/flash.c View File

@@ -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 */


+ 1
- 0
src/flash/flash.h View File

@@ -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);


+ 29
- 21
src/helper/command.c View File

@@ -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;


+ 302
- 296
src/jtag/usbprog.c View File

@@ -1,14 +1,14 @@
/***************************************************************************
* 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);
}
cur_state = cmd->path[state_count];
state_count++;
num_states--;
}
end_state = cur_state;
}


void usbprog_runtest(int num_cycles)
{
int i;

enum tap_state saved_end_state = end_state;


int i;
/* only do a state_move when we're not already in RTI */
if (cur_state != TAP_RTI)
{
usbprog_end_state(TAP_RTI);
usbprog_state_move();
}
/* execute num_cycles */
if(num_cycles>0)
if (cur_state != TAP_RTI)
{
usbprog_end_state(TAP_RTI);
usbprog_state_move();
}
/* execute num_cycles */
if (num_cycles > 0)
{
usbprog_jtag_tms_send(usbprog_jtag_handle);
usbprog_write(0, 0, 0);
}
else {
else
{
usbprog_jtag_tms_send(usbprog_jtag_handle);
//INFO("NUM CYCLES %i",num_cycles);
}
for (i = 0; i < num_cycles; i++)
{
usbprog_write(1, 0, 0);
usbprog_write(0, 0, 0);
}
/* finish in end_state */
for (i = 0; i < num_cycles; i++)
{
usbprog_write(1, 0, 0);
usbprog_write(0, 0, 0);
}
/* finish in end_state */
/*
usbprog_end_state(saved_end_state);
if (cur_state != end_state)
usbprog_state_move();
usbprog_end_state(saved_end_state);
if (cur_state != end_state)
usbprog_state_move();
*/
}



void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
{
enum tap_state saved_end_state = end_state;
int bit_cnt;

if (ir_scan)
usbprog_end_state(TAP_SI);
else
usbprog_end_state(TAP_SD);

enum tap_state saved_end_state = end_state;
if (ir_scan)
usbprog_end_state(TAP_SI);
else
usbprog_end_state(TAP_SD);
//usbprog_jtag_tms_send(usbprog_jtag_handle);
usbprog_state_move();
usbprog_end_state(saved_end_state);
usbprog_state_move();
usbprog_end_state(saved_end_state);
usbprog_jtag_tms_send(usbprog_jtag_handle);

if (type == SCAN_OUT) {
usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);
}
if (type == SCAN_IN) {
usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);
}
if (type == SCAN_IO) {
usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);
}
if (ir_scan)
cur_state = TAP_PI;
else
cur_state = TAP_PD;

if (cur_state != end_state)
usbprog_state_move();
if (type == SCAN_OUT)
{
usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);
}
if (type == SCAN_IN)
{
usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);
}
if (type == SCAN_IO)
{
usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);
}
if (ir_scan)
cur_state = TAP_PI;
else
cur_state = TAP_PD;
if (cur_state != end_state)
usbprog_state_move();
}

/*************** jtag wrapper functions *********************/

void usbprog_write(int tck, int tms, int tdi)
{
unsigned char output_value=0x00;
if (tms)
output_value |= (1<<TMS_BIT);
if (tdi)
output_value |= (1<<TDI_BIT);
if (tck)
output_value |= (1<<TCK_BIT);
usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
unsigned char output_value=0x00;
if (tms)
output_value |= (1<<TMS_BIT);
if (tdi)
output_value |= (1<<TDI_BIT);
if (tck)
output_value |= (1<<TCK_BIT);
usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
}

/* (1) assert or (0) deassert reset lines */
void usbprog_reset(int trst, int srst)
{
DEBUG("trst: %i, srst: %i", trst, srst);
if(trst)
usbprog_jtag_set_bit(usbprog_jtag_handle,5,0);
else
usbprog_jtag_set_bit(usbprog_jtag_handle,5,1);
if(srst)
usbprog_jtag_set_bit(usbprog_jtag_handle,4,0);
else
usbprog_jtag_set_bit(usbprog_jtag_handle,4,1);
DEBUG("trst: %i, srst: %i", trst, srst);
if (trst)
usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
else
usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
if (srst)
usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
else
usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
}



/*************** jtag lowlevel functions ********************/

struct usb_bus *busses;

struct usb_bus *busses;
struct usbprog_jtag* usbprog_jtag_open()
{
struct usb_dev_handle* usb_handle;
struct usb_bus *bus;
struct usb_device *dev;
struct usbprog_jtag * tmp;
struct usbprog_jtag *tmp;
tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));
usb_set_debug(10);
usb_set_debug(10);
usb_init();
usb_find_busses();
usb_find_devices();

busses = usb_get_busses();
/* find usbprog_jtag device in usb bus */

for (bus = busses; bus; bus = bus->next){
for (dev = bus->devices; dev; dev = dev->next){
for (bus = busses; bus; bus = bus->next)
{
for (dev = bus->devices; dev; dev = dev->next)
{
/* condition for sucessfully hit (too bad, I only check the vendor id)*/
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) {
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)
{
tmp->usb_handle = usb_open(dev);
usb_set_configuration (tmp->usb_handle,1);
usb_set_configuration(tmp->usb_handle, 1);
usb_claim_interface(tmp->usb_handle, 0);
usb_set_altinterface(tmp->usb_handle,0);
usb_set_altinterface(tmp->usb_handle, 0);
return tmp;
}
}
@@ -447,22 +438,22 @@ usb_set_debug(10);
return 0;
}


void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
{
usb_close(usbprog_jtag->usb_handle);
free(usbprog_jtag);
}


unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
{
int res = usb_bulk_write(usbprog_jtag->usb_handle,3,msg,msglen,100);
if(msg[0]==2||msg[0]==1||msg[0]==4||msg[0]==0||msg[0]==6||msg[0]==0x0A||msg[0]==9)
int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);
if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
(msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
return 1;
if(res == msglen) {
if (res == msglen)
{
//INFO("HALLLLOOO %i",(int)msg[0]);
res = usb_bulk_read(usbprog_jtag->usb_handle,0x82, msg, 2, 100);
res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
if (res > 0)
return (unsigned char)msg[1];
else
@@ -478,92 +469,103 @@ void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
}


void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
{
char tmp[64]; // fastes packet size for usb controller
int send_bits,bufindex=0,fillindex=0,i,j,complete=size,loops;
int send_bits, bufindex = 0, fillindex = 0, i, loops;
char swap;
// 61 byte can be transfered (488 bit)
while(size > 0) {
if(size > 488) {
while (size > 0)
{
if (size > 488)
{
send_bits = 488;
size = size - 488;
loops = 61;
} else {
}
else
{
send_bits = size;
loops = size/8;
loops = size / 8;
loops++;
size = 0;
}
tmp[0] = WRITE_AND_READ;
tmp[1] = (char)(send_bits>>8); // high
tmp[2] = (char)(send_bits); // low
i=0;

for(i=0;i < loops ;i++) {
tmp[3+i]=buffer[bufindex];
tmp[1] = (char)(send_bits >> 8); // high
tmp[2] = (char)(send_bits); // low
i = 0;
for (i = 0; i < loops; i++)
{
tmp[3 + i] = buffer[bufindex];
bufindex++;
}
if(usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,64,1000)==64)
if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)
{
//INFO("HALLLLOOO2 %i",(int)tmp[0]);
usleep(1);
int timeout=0;
while(usb_bulk_read(usbprog_jtag->usb_handle,0x82, tmp, 64, 1000) < 1){
int timeout = 0;
while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)
{
timeout++;
if(timeout>10)
if (timeout > 10)
break;
}

for(i=0;i<loops ;i++) {
swap = tmp[3+i];
for (i = 0; i < loops; i++)
{
swap = tmp[3 + i];
buffer[fillindex++] = swap;
}
}
}
}


void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
{
char tmp[64]; // fastes packet size for usb controller
int send_bits,bufindex=0,fillindex=0,i,j,complete=size,loops;
int send_bits, fillindex = 0, i, loops;

char swap;
// 61 byte can be transfered (488 bit)
while(size > 0) {
if(size > 488) {
while (size > 0)
{
if (size > 488)
{
send_bits = 488;
size = size - 488;
loops = 61;
} else {
}
else
{
send_bits = size;
loops = size/8;
loops = size / 8;
loops++;
size = 0;
}
tmp[0] = WRITE_AND_READ;
tmp[1] = (char)(send_bits>>8); // high
tmp[2] = (char)(send_bits); // low
tmp[1] = (char)(send_bits >> 8); // high
tmp[2] = (char)(send_bits); // low
usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,3,1000);
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
//INFO("HALLLLOOO3 %i",(int)tmp[0]);
int timeout=0;
int timeout = 0;
usleep(1);
while(usb_bulk_read(usbprog_jtag->usb_handle,0x82, tmp, 64, 10) < 1){
while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)
{
timeout++;
if(timeout>10)
if (timeout > 10)
break;
}

for(i=0;i<loops ;i++) {
swap = tmp[3+i];
for (i = 0; i < loops; i++)
{
swap = tmp[3 + i];
buffer[fillindex++] = swap;
}
}
@@ -572,15 +574,19 @@ void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int
void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
{
char tmp[64]; // fastes packet size for usb controller
int send_bits,bufindex=0,fillindex=0,i,j,complete=size,loops;
char swap;
int send_bits, bufindex = 0, i, loops;
// 61 byte can be transfered (488 bit)
while(size > 0) {
if(size > 488) {
while (size > 0)
{
if (size > 488)
{
send_bits = 488;
size = size - 488;
loops = 61;
} else {
}
else
{
send_bits = size;
loops = size/8;
//if(loops==0)
@@ -588,31 +594,30 @@ void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, in
size = 0;
}
tmp[0] = WRITE_TDI;
tmp[1] = (char)(send_bits>>8); // high
tmp[2] = (char)(send_bits); // low
i=0;

for(i=0;i < loops ;i++) {
tmp[3+i]=buffer[bufindex];
tmp[1] = (char)(send_bits >> 8); // high
tmp[2] = (char)(send_bits); // low
i = 0;
for (i = 0; i < loops; i++)
{
tmp[3 + i] = buffer[bufindex];
bufindex++;
}
usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,64,1000);
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
}
}


void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
{
usbprog_jtag_tms_collect(tms_scan);
}


void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
{
char tmp[2];
tmp[0] = PORT_DIRECTION;
tmp[1] = (char)direction;
usbprog_jtag_message(usbprog_jtag,tmp,2);
usbprog_jtag_message(usbprog_jtag, tmp, 2);
}

void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)
@@ -620,7 +625,7 @@ void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char va
char tmp[2];
tmp[0] = PORT_SET;
tmp[1] = (char)value;
usbprog_jtag_message(usbprog_jtag,tmp,2);
usbprog_jtag_message(usbprog_jtag, tmp, 2);
}

unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
@@ -628,20 +633,19 @@ unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
char tmp[2];
tmp[0] = PORT_GET;
tmp[1] = 0x00;
return usbprog_jtag_message(usbprog_jtag,tmp,2);
return usbprog_jtag_message(usbprog_jtag, tmp, 2);
}


void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)
{
char tmp[3];
tmp[0] = PORT_SETBIT;
tmp[1] = (char)bit;
if(value==1)
if (value == 1)
tmp[2] = 0x01;
else
tmp[2] = 0x00;
usbprog_jtag_message(usbprog_jtag,tmp,3);
usbprog_jtag_message(usbprog_jtag, tmp, 3);
}

int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
@@ -649,29 +653,31 @@ int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
char tmp[2];
tmp[0] = PORT_GETBIT;
tmp[1] = (char)bit;
if(usbprog_jtag_message(usbprog_jtag,tmp,2)>0)
if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
return 1;
else
return 0;
}

void usbprog_jtag_tms_collect(char tms_scan){
tms_chain[tms_chain_index]=tms_scan;
void usbprog_jtag_tms_collect(char tms_scan)
{
tms_chain[tms_chain_index] = tms_scan;
tms_chain_index++;
}

void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag){
void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
{
int i;
//INFO("TMS SEND");
if(tms_chain_index>0) {
char tmp[tms_chain_index+2];
if (tms_chain_index > 0)
{
char tmp[tms_chain_index + 2];
tmp[0] = WRITE_TMS_CHAIN;
tmp[1] = (char)(tms_chain_index);
for(i=0;i<tms_chain_index+1;i++)
tmp[2+i] = tms_chain[i];
usb_bulk_write(usbprog_jtag->usb_handle,3,tmp,tms_chain_index+2,1000);
tms_chain_index=0;
for (i = 0; i < tms_chain_index + 1; i++)
tmp[2 + i] = tms_chain[i];
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
tms_chain_index = 0;
}
}


+ 1
- 1
src/server/Makefile.am View File

@@ -1,4 +1,4 @@
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
noinst_LIBRARIES = libserver.a
noinst_HEADERS = server.h telnet_server.h gdb_server.h


+ 318
- 12
src/server/gdb_server.c View File

@@ -28,11 +28,11 @@
#include "server.h"
#include "log.h"
#include "binarybuffer.h"
#include "jtag.h"
#include "breakpoints.h"
#include "flash.h"
#include "target_request.h"

#define __USE_GNU
#include <string.h>
#include <errno.h>
#include <unistd.h>
@@ -52,8 +52,14 @@ enum gdb_detach_mode
GDB_DETACH_NOTHING
};

/* target behaviour on gdb detach */
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)
{
switch (target->debug_reason)
@@ -77,7 +83,10 @@ int gdb_last_signal(target_t *target)
int gdb_get_char(connection_t *connection, int* next_char)
{
gdb_connection_t *gdb_con = connection->priv;

#ifdef _DEBUG_GDB_IO_
char *debug_buffer;
#endif

if (gdb_con->buf_cnt-- > 0)
{
@@ -109,6 +118,8 @@ int gdb_get_char(connection_t *connection, int* next_char)
break;
case WSAECONNABORTED:
return ERROR_SERVER_REMOTE_CLOSED;
case WSAECONNRESET:
return ERROR_SERVER_REMOTE_CLOSED;
default:
ERROR("read: %d", errno);
exit(-1);
@@ -130,11 +141,13 @@ int gdb_get_char(connection_t *connection, int* next_char)
#endif
}

#ifdef _DEBUG_GDB_IO_
debug_buffer = malloc(gdb_con->buf_cnt + 1);
memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
debug_buffer[gdb_con->buf_cnt] = 0;
DEBUG("received '%s'", debug_buffer);
free(debug_buffer);
#endif

gdb_con->buf_p = gdb_con->buffer;
gdb_con->buf_cnt--;
@@ -245,7 +258,9 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;

#ifdef _DEBUG_GDB_IO_
DEBUG("character: '%c'", character);
#endif

switch (character)
{
@@ -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)
{
connection_t *connection = context->output_handler_priv;
gdb_connection_t *gdb_connection = connection->priv;
char *hex_buffer;
int i, bin_size;

/* check if output is enabled */
if (gdb_connection->output_disable)
{
return ERROR_OK;
}
bin_size = strlen(line);

hex_buffer = malloc(bin_size*2 + 4);
@@ -345,6 +368,30 @@ int gdb_output(struct command_context_s *context, char* line)
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)
{
connection_t *connection = priv;
@@ -378,6 +425,9 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
gdb_connection->frontend_state = TARGET_RUNNING;
}
break;
case TARGET_EVENT_GDB_PROGRAM:
gdb_program_handler(target, event, connection->cmd_ctx);
break;
default:
break;
}
@@ -400,7 +450,8 @@ int gdb_new_connection(connection_t *connection)
gdb_connection->ctrl_c = 0;
gdb_connection->frontend_state = TARGET_HALTED;
gdb_connection->vflash_image = NULL;

gdb_connection->output_disable = 0;
/* output goes through gdb 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,
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))
{
*pos += ret;
return;
}
/* there was just enough or not enough space, allocate more. */
first = 0;
}
}

static int decode_xfer_read (char *buf, char **annex, int *ofs, unsigned int *len)
{
char *separator;
/* Extract and NUL-terminate the annex. */
*annex = buf;
while (*buf && *buf != ':')
buf++;
if (*buf == '\0')
return -1;
*buf++ = 0;
/* After the read marker and annex, qXfer looks like a
* traditional 'm' packet. */
*ofs = strtoul(buf, &separator, 16);

if (*separator != ',')
return -1;

*len = strtoul(separator+1, NULL, 16);
return 0;
}

int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
{
char buffer[GDB_BUFFER_SIZE];
command_context_t *cmd_ctx = connection->cmd_ctx;

if (strstr(packet, "qRcmd,"))
{
if (packet_size > 6)
@@ -1196,13 +1313,12 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
gdb_put_packet(connection, "OK", 2);
return ERROR_OK;
}

if (strstr(packet, "qCRC:"))
else if (strstr(packet, "qCRC:"))
{
if (packet_size > 5)
{
int retval;
u8 gdb_reply[9];
u8 gdb_reply[10];
char *separator;
u32 checksum;
u32 addr = 0;
@@ -1219,13 +1335,13 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
return ERROR_SERVER_REMOTE_CLOSED;
}
len = strtoul(separator+1, NULL, 16);
len = strtoul(separator + 1, NULL, 16);
retval = target_checksum_memory(target, addr, len, &checksum);
if (retval == ERROR_OK)
{
snprintf(gdb_reply, 9, "C%2.2x", checksum);
snprintf(gdb_reply, 10, "C%8.8x", checksum);
gdb_put_packet(connection, gdb_reply, 9);
}
else
@@ -1237,6 +1353,119 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
return ERROR_OK;
}
}
else if (strstr(packet, "qSupported"))
{
/* we currently support packet size and qXfer:memory-map:read (if enabled)
* disable qXfer:features:read for the moment */
sprintf(buffer, "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
(GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-');
gdb_put_packet(connection, buffer, strlen(buffer));
return ERROR_OK;
}
else if (strstr(packet, "qXfer:memory-map:read::"))
{
/* We get away with only specifying flash here. Regions that are not
* specified are treated as if we provided no memory map(if not we
* could detect the holes and mark them as RAM).
* Normally we only execute this code once, but no big deal if we
* have to regenerate it a couple of times. */
flash_bank_t *p;
char *xml = NULL;
int size = 0;
int pos = 0;
int retval = ERROR_OK;
int offset;
int length;
char *separator;
/* skip command character */
packet += 23;
offset = strtoul(packet, &separator, 16);
length = strtoul(separator + 1, &separator, 16);
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
int i = 0;
for (;;)
{
p = get_flash_bank_by_num(i);
if (p == NULL)
break;
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
"<property name=\"blocksize\">0x%x</property>\n" \
"</memory>\n", \
p->base, p->size, p->size/p->num_sectors);
i++;
}
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");

if (retval != ERROR_OK)
{
gdb_send_error(connection, retval);
return retval;
}
if (offset + length > pos)
{
length = pos - offset;
}

char *t = malloc(length + 1);
t[0] = 'l';
memcpy(t + 1, xml + offset, length);
gdb_put_packet(connection, t, length + 1);
free(t);
free(xml);
return ERROR_OK;
}
else if (strstr(packet, "qXfer:features:read:"))
{
char *xml = NULL;
int size = 0;
int pos = 0;
int retval = ERROR_OK;
int offset;
int length;
char *annex;
/* skip command character */
packet += 20;
if (decode_xfer_read( packet, &annex, &offset, &length ) < 0)
{
gdb_send_error(connection, 01);
return ERROR_OK;
}
if (strcmp(annex, "target.xml") != 0)
{
gdb_send_error(connection, 01);
return ERROR_OK;
}
xml_printf(&retval, &xml, &pos, &size, \
"l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
if (retval != ERROR_OK)
{
gdb_send_error(connection, retval);
return retval;
}
gdb_put_packet(connection, xml, strlen(xml) + 1);
free(xml);
return ERROR_OK;
}
gdb_put_packet(connection, "", 0);
return ERROR_OK;
@@ -1248,10 +1477,19 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
gdb_service_t *gdb_service = connection->service->priv;
int result;

/* if flash programming disabled - send a empty reply */
if (gdb_flash_program == 0)
{
gdb_put_packet(connection, "", 0);
return ERROR_OK;
}
if (strstr(packet, "vFlashErase:"))
{
unsigned long addr;
unsigned long length;
char *parse = packet + 12;
if (*parse == '\0')
{
@@ -1274,7 +1512,17 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
ERROR("incomplete vFlashErase packet received, dropping connection");
return ERROR_SERVER_REMOTE_CLOSED;
}

/* disable gdb output while programming */
gdb_connection->output_disable = 1;
/* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */
flash_set_dirty();
/* perform any target specific operations before the erase */
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM);
/* perform erase */
if ((result = flash_erase(gdb_service->target, addr, length)) != ERROR_OK)
{
@@ -1286,7 +1534,10 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
}
else
gdb_put_packet(connection, "OK", 2);

/* reenable gdb output */
gdb_connection->output_disable = 0;
return ERROR_OK;
}

@@ -1309,6 +1560,9 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
}
length = packet_size - (parse - packet);
/* disable gdb output while programming */
gdb_connection->output_disable = 1;
/* create a new image if there isn't already one */
if (gdb_connection->vflash_image == NULL)
{
@@ -1321,6 +1575,9 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p

gdb_put_packet(connection, "OK", 2);

/* reenable gdb output */
gdb_connection->output_disable = 0;
return ERROR_OK;
}

@@ -1329,6 +1586,9 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
u32 written;
char *error_str;

/* disable gdb output while programming */
gdb_connection->output_disable = 1;
/* process the flashing buffer */
if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, 0)) != ERROR_OK)
{
@@ -1352,7 +1612,10 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
image_close(gdb_connection->vflash_image);
free(gdb_connection->vflash_image);
gdb_connection->vflash_image = NULL;

/* reenable gdb output */
gdb_connection->output_disable = 0;
return ERROR_OK;
}

@@ -1580,12 +1843,55 @@ int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char
return ERROR_OK;
}

int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
if (argc == 1)
{
if (strcmp(args[0], "enable") == 0)
{
gdb_use_memory_map = 1;
return ERROR_OK;
}
else if (strcmp(args[0], "disable") == 0)
{
gdb_use_memory_map = 0;
return ERROR_OK;
}
}
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
return ERROR_OK;
}

int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
if (argc == 1)
{
if (strcmp(args[0], "enable") == 0)
{
gdb_flash_program = 1;
return ERROR_OK;
}
else if (strcmp(args[0], "disable") == 0)
{
gdb_flash_program = 0;
return ERROR_OK;
}
}
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
return ERROR_OK;
}

int gdb_register_commands(command_context_t *command_context)
{
register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
COMMAND_CONFIG, "");
register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
COMMAND_CONFIG, "");
register_command(command_context, NULL, "gdb_memory_map", handle_gdb_memory_map_command,
COMMAND_CONFIG, "");
register_command(command_context, NULL, "gdb_flash_program", handle_gdb_flash_program_command,
COMMAND_CONFIG, "");
return ERROR_OK;
}

+ 1
- 0
src/server/gdb_server.h View File

@@ -34,6 +34,7 @@ typedef struct gdb_connection_s
int ctrl_c;
enum target_state frontend_state;
image_t *vflash_image;
int output_disable;
} gdb_connection_t;

typedef struct gdb_service_s


+ 16
- 25
src/target/image.c View File

@@ -360,12 +360,12 @@ int image_elf_read_headers(image_t *image)
return ERROR_FILEIO_OPERATION_FAILED;
}

if (strncmp((char*)elf->header->e_ident,ELFMAG,SELFMAG)!=0)
if (strncmp((char*)elf->header->e_ident,ELFMAG,SELFMAG) != 0)
{
ERROR("invalid ELF file, bad magic number");
return ERROR_IMAGE_FORMAT_ERROR;
}
if (elf->header->e_ident[EI_CLASS]!=ELFCLASS32)
if (elf->header->e_ident[EI_CLASS] != ELFCLASS32)
{
ERROR("invalid ELF file, only 32bits files are supported");
return ERROR_IMAGE_FORMAT_ERROR;
@@ -373,28 +373,28 @@ int image_elf_read_headers(image_t *image)


elf->endianness = elf->header->e_ident[EI_DATA];
if ((elf->endianness!=ELFDATA2LSB)
&&(elf->endianness!=ELFDATA2MSB))
if ((elf->endianness != ELFDATA2LSB)
&&(elf->endianness != ELFDATA2MSB))
{
ERROR("invalid ELF file, unknown endianess setting");
return ERROR_IMAGE_FORMAT_ERROR;
}

elf->segment_count = field16(elf,elf->header->e_phnum);
if (elf->segment_count==0)
elf->segment_count = field16(elf, elf->header->e_phnum);
if (elf->segment_count == 0)
{
ERROR("invalid ELF file, no program headers");
return ERROR_IMAGE_FORMAT_ERROR;
}

elf->segments = malloc(elf->segment_count*sizeof(Elf32_Phdr));
elf->segments = malloc(elf->segment_count * sizeof(Elf32_Phdr));

if ((retval = fileio_read(&elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), (u8*)elf->segments, &read_bytes)) != ERROR_OK)
if ((retval = fileio_read(&elf->fileio, elf->segment_count * sizeof(Elf32_Phdr), (u8*)elf->segments, &read_bytes)) != ERROR_OK)
{
ERROR("cannot read ELF segment headers, read failed");
return retval;
}
if (read_bytes != elf->segment_count*sizeof(Elf32_Phdr))
if (read_bytes != elf->segment_count * sizeof(Elf32_Phdr))
{
ERROR("cannot read ELF segment headers, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
@@ -411,16 +411,16 @@ int image_elf_read_headers(image_t *image)
{
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
{
image->sections[j].size = field32(elf,elf->segments[i].p_memsz);
image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
image->sections[j].size = field32(elf, elf->segments[i].p_memsz);
image->sections[j].base_address = field32(elf, elf->segments[i].p_paddr);
image->sections[j].private = &elf->segments[i];
image->sections[j].flags = field32(elf,elf->segments[i].p_flags);
image->sections[j].flags = field32(elf, elf->segments[i].p_flags);
j++;
}
}
image->start_address_set = 1;
image->start_address = field32(elf,elf->header->e_entry);
image->start_address = field32(elf, elf->header->e_entry);

return ERROR_OK;
}
@@ -442,9 +442,9 @@ int image_elf_read_section(image_t *image, int section, u32 offset, u32 size, u8
/* maximal size present in file for the current segment */
read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
DEBUG("read elf: size = 0x%x at 0x%x", read_size,
field32(elf,segment->p_offset) + offset);
field32(elf, segment->p_offset) + offset);
/* read initialized area of the segment */
if ((retval = fileio_seek(&elf->fileio, field32(elf,segment->p_offset) + offset)) != ERROR_OK)
if ((retval = fileio_seek(&elf->fileio, field32(elf, segment->p_offset) + offset)) != ERROR_OK)
{
ERROR("cannot find ELF segment content, seek failed");
return retval;
@@ -462,16 +462,7 @@ int image_elf_read_section(image_t *image, int section, u32 offset, u32 size, u8
if (!size)
return ERROR_OK;
}
/* if there is remaining zeroed area in current segment */
if (offset < field32(elf, segment->p_memsz))
{
/* fill zeroed part (BSS) of the segment */
read_size = MIN(size, field32(elf, segment->p_memsz) - offset);
DEBUG("zero fill: size = 0x%x", read_size);
memset(buffer, 0, read_size);
*size_read += read_size;
}
return ERROR_OK;
}



+ 7
- 0
src/target/target.c View File

@@ -1040,6 +1040,7 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a
(*last_target_p)->reset_script = NULL;
(*last_target_p)->post_halt_script = NULL;
(*last_target_p)->pre_resume_script = NULL;
(*last_target_p)->gdb_program_script = NULL;
(*last_target_p)->working_area = 0x0;
(*last_target_p)->working_area_size = 0x0;
@@ -1120,6 +1121,12 @@ int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, c
free(target->pre_resume_script);
target->pre_resume_script = strdup(args[2]);
}
else if (strcmp(args[1], "gdb_program_config") == 0)
{
if (target->gdb_program_script)
free(target->gdb_program_script);
target->gdb_program_script = strdup(args[2]);
}
else
{
ERROR("unknown event type: '%s", args[1]);


+ 2
- 0
src/target/target.h View File

@@ -157,6 +157,7 @@ typedef struct target_s
char *reset_script; /* script file to initialize the target after a reset */
char *post_halt_script; /* script file to execute after the target halted */
char *pre_resume_script; /* script file to execute before the target resumed */
char *gdb_program_script; /* script file to execute before programming vis gdb */
u32 working_area; /* working area (initialized RAM) */
u32 working_area_size; /* size in bytes */
u32 backup_working_area; /* whether the content of the working area has to be preserved */
@@ -180,6 +181,7 @@ enum target_event
TARGET_EVENT_RESET, /* target entered reset */
TARGET_EVENT_DEBUG_HALTED, /* target entered debug state, but was executing on behalf of the debugger */
TARGET_EVENT_DEBUG_RESUMED, /* target resumed to execute on behalf of the debugger */
TARGET_EVENT_GDB_PROGRAM /* target about to be be programmed by gdb */
};

typedef struct target_event_callback_s


Loading…
Cancel
Save