gdb: connect will now fail if flash autoprobe fails

This stops GDB from launching with an empty memory map,
making gdb load w/flashing fail for no obvious reason.

The error message points in the direction of the gdb-attach
event that can be set up to issue a halt or "reset init"
which will put GDB in a well defined stated upon attach
and thus have a robust flash autoprobe.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
This commit is contained in:
Øyvind Harboe 2010-05-04 13:26:52 +02:00
parent 812e21ac39
commit 82ea640830
4 changed files with 44 additions and 24 deletions

View File

@ -220,22 +220,25 @@ struct flash_bank *get_flash_bank_by_name(const char *name)
return NULL; return NULL;
} }
struct flash_bank *get_flash_bank_by_num(int num) int get_flash_bank_by_num(int num, struct flash_bank **bank)
{ {
struct flash_bank *p = get_flash_bank_by_num_noprobe(num); struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
int retval; int retval;
if (p == NULL) if (p == NULL)
return NULL; {
return ERROR_FAIL;
}
retval = p->driver->auto_probe(p); retval = p->driver->auto_probe(p);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
LOG_ERROR("auto_probe failed %d\n", retval); LOG_ERROR("auto_probe failed %d\n", retval);
return NULL; return retval;
} }
return p; *bank = p;
return ERROR_OK;
} }
/* lookup flash bank by address */ /* lookup flash bank by address */

View File

@ -157,9 +157,10 @@ struct flash_bank *get_flash_bank_by_name(const char *name);
/** /**
* Returns a flash bank by the specified flash_bank_s bank_number, @a num. * Returns a flash bank by the specified flash_bank_s bank_number, @a num.
* @param num The flash bank number. * @param num The flash bank number.
* @returns A struct flash_bank for flash bank @a num, or NULL * @param bank returned bank if fn returns ERROR_OK
* @returns ERROR_OK if successful
*/ */
struct flash_bank *get_flash_bank_by_num(int num); int get_flash_bank_by_num(int num, struct flash_bank **bank);
/** /**
* Retreives @a bank from a command argument, reporting errors parsing * Retreives @a bank from a command argument, reporting errors parsing
* the bank identifier or retreiving the specified bank. The bank * the bank identifier or retreiving the specified bank. The bank

View File

@ -42,13 +42,7 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
unsigned bank_num; unsigned bank_num;
COMMAND_PARSE_NUMBER(uint, name, bank_num); COMMAND_PARSE_NUMBER(uint, name, bank_num);
*bank = get_flash_bank_by_num(bank_num); return get_flash_bank_by_num(bank_num, bank);
if (!*bank)
{
command_print(CMD_CTX, "flash bank '%s' not found", name);
return ERROR_INVALID_ARGUMENTS;
}
return ERROR_OK;
} }
@ -310,9 +304,12 @@ COMMAND_HANDLER(handle_flash_erase_command)
uint32_t last; uint32_t last;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr);
struct flash_bank *p = get_flash_bank_by_num(bank_nr);
if (!p) struct flash_bank *p;
return ERROR_OK; int retval;
retval = get_flash_bank_by_num(bank_nr, &p);
if (retval != ERROR_OK)
return retval;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
if (strcmp(CMD_ARGV[2], "last") == 0) if (strcmp(CMD_ARGV[2], "last") == 0)
@ -320,7 +317,6 @@ COMMAND_HANDLER(handle_flash_erase_command)
else else
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
int retval;
if ((retval = flash_check_sector_parameters(CMD_CTX, if ((retval = flash_check_sector_parameters(CMD_CTX,
first, last, p->num_sectors)) != ERROR_OK) first, last, p->num_sectors)) != ERROR_OK)
return retval; return retval;
@ -350,9 +346,10 @@ COMMAND_HANDLER(handle_flash_protect_command)
uint32_t last; uint32_t last;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr);
struct flash_bank *p = get_flash_bank_by_num(bank_nr); struct flash_bank *p;
if (!p) int retval = get_flash_bank_by_num(bank_nr, &p);
return ERROR_OK; if (retval != ERROR_OK)
return retval;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
if (strcmp(CMD_ARGV[2], "last") == 0) if (strcmp(CMD_ARGV[2], "last") == 0)
@ -363,7 +360,6 @@ COMMAND_HANDLER(handle_flash_protect_command)
bool set; bool set;
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
int retval;
if ((retval = flash_check_sector_parameters(CMD_CTX, if ((retval = flash_check_sector_parameters(CMD_CTX,
first, last, p->num_sectors)) != ERROR_OK) first, last, p->num_sectors)) != ERROR_OK)
return retval; return retval;

View File

@ -855,6 +855,26 @@ static int gdb_new_connection(struct connection *connection)
gdb_putback_char(connection, initial_ack); gdb_putback_char(connection, initial_ack);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH);
if (gdb_use_memory_map)
{
/* Connect must fail if the memory map can't be set up correctly.
*
* This will cause an auto_probe to be invoked, which is either
* a no-op or it will fail when the target isn't ready(e.g. not halted).
*/
int i;
for (i = 0; i < flash_get_bank_count(); i++)
{
struct flash_bank *p;
retval = get_flash_bank_by_num(i, &p);
if (retval != ERROR_OK)
{
LOG_ERROR("Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect.");
return retval;
}
}
}
gdb_actual_connections++; gdb_actual_connections++;
LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s", LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s",
gdb_actual_connections, gdb_actual_connections,
@ -1692,10 +1712,10 @@ static int gdb_memory_map(struct connection *connection,
banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count()); banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
for (i = 0; i < flash_get_bank_count(); i++) { for (i = 0; i < flash_get_bank_count(); i++) {
p = get_flash_bank_by_num(i); retval = get_flash_bank_by_num(i, &p);
if (p == NULL) { if (retval != ERROR_OK)
{
free(banks); free(banks);
retval = ERROR_FAIL;
gdb_send_error(connection, retval); gdb_send_error(connection, retval);
return retval; return retval;
} }