Commit 815c3b35 authored by oharboe's avatar oharboe
Browse files

- "flash write_binary" is now "flash write_bank" to clarify the focus of the
 command and reduce confusion with "flash write_image".
- retired deprecated "flash erase" & "flash write".
- added flash_driver_protect/write/erase() that are wafer thin frontend
 functions to low level driver functions. They implement checks
 that were inconsistently handled by the drivers, e.g. check for
 target halted was done in a spotty fashion.
- use return ERROR_COMMAND_SYNTAX_ERROR to print out
 syntax of command instead of having lots of inlined replicas of
 the command line syntax(some of which were wrong).
- use logging instead of dubious translation of error values to
 human understandable explanations of why things failed.
 The lower levels log the precise reason and the higher
 levels can ammend context as the error propagates up
 the call stack.
- simplified flash API slightly with logging instead of
 allocating and returning information that the caller then
 has to translate into print statements.



git-svn-id: svn://svn.berlios.de/openocd/trunk@337 b42882b7-edfa-0310-969c-e2dbd0fdcd60
parent d8456e48
This diff is collapsed.
...@@ -1375,11 +1375,11 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, ...@@ -1375,11 +1375,11 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
} }
/* allocate working area */ /* allocate working area */
if (target_alloc_working_area(target, 24 * 4, retval=target_alloc_working_area(target, 24 * 4,
&cfi_info->write_algorithm) != ERROR_OK) &cfi_info->write_algorithm);
if (retval != ERROR_OK)
{ {
WARNING("no working area available, can't do block memory writes"); return retval;
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
/* write algorithm code to working area */ /* write algorithm code to working area */
...@@ -1645,11 +1645,6 @@ int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) ...@@ -1645,11 +1645,6 @@ int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
int i; int i;
int retval; int retval;
if (bank->target->state != TARGET_HALTED)
{
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) if (offset + count > bank->size)
return ERROR_FLASH_DST_OUT_OF_BANK; return ERROR_FLASH_DST_OUT_OF_BANK;
......
This diff is collapsed.
/*************************************************************************** /***************************************************************************
* Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de * * Dominic.Rath@gmx.de *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. * * GNU General Public License for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the * * along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_H #ifndef FLASH_H
#define FLASH_H #define FLASH_H
#include "target.h" #include "target.h"
#include "image.h" #include "image.h"
#define FLASH_MAX_ERROR_STR (128) #define FLASH_MAX_ERROR_STR (128)
typedef struct flash_sector_s typedef struct flash_sector_s
{ {
u32 offset; u32 offset;
u32 size; u32 size;
int is_erased; int is_erased;
int is_protected; int is_protected;
} flash_sector_t; } flash_sector_t;
struct flash_bank_s; struct flash_bank_s;
typedef struct flash_driver_s typedef struct flash_driver_s
{ {
char *name; char *name;
int (*register_commands)(struct command_context_s *cmd_ctx); int (*register_commands)(struct command_context_s *cmd_ctx);
int (*flash_bank_command)(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); int (*flash_bank_command)(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
int (*erase)(struct flash_bank_s *bank, int first, int last); /* low level flash erase. Only invoke from flash_driver_erase()
int (*protect)(struct flash_bank_s *bank, int set, int first, int last); *
int (*write)(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); * Will only be invoked when target is halted.
int (*probe)(struct flash_bank_s *bank); */
int (*erase_check)(struct flash_bank_s *bank); int (*erase)(struct flash_bank_s *bank, int first, int last);
int (*protect_check)(struct flash_bank_s *bank); /* invoked only from flash_driver_protect().
int (*info)(struct flash_bank_s *bank, char *buf, int buf_size); *
int (*auto_probe)(struct flash_bank_s *bank); * Only invoked if target is halted
} flash_driver_t; */
int (*protect)(struct flash_bank_s *bank, int set, int first, int last);
typedef struct flash_bank_s /* low level flash write. Will only be invoked if the target is halted.
{ * use the flash_driver_write() wrapper to invoke.
target_t *target; */
flash_driver_t *driver; int (*write)(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
void *driver_priv; int (*probe)(struct flash_bank_s *bank);
u32 base; int (*erase_check)(struct flash_bank_s *bank);
u32 size; int (*protect_check)(struct flash_bank_s *bank);
int chip_width; int (*info)(struct flash_bank_s *bank, char *buf, int buf_size);
int bus_width; int (*auto_probe)(struct flash_bank_s *bank);
int num_sectors; } flash_driver_t;
flash_sector_t *sectors;
struct flash_bank_s *next; typedef struct flash_bank_s
} flash_bank_t; {
target_t *target;
extern int flash_register_commands(struct command_context_s *cmd_ctx); flash_driver_t *driver;
extern int flash_init_drivers(struct command_context_s *cmd_ctx); void *driver_priv;
u32 base;
extern int flash_erase_address_range(target_t *target, u32 addr, u32 length); u32 size;
extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed, int erase); int chip_width;
extern void flash_set_dirty(void); int bus_width;
int num_sectors;
extern flash_bank_t *get_flash_bank_by_num(int num); flash_sector_t *sectors;
extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr); struct flash_bank_s *next;
} flash_bank_t;
#define ERROR_FLASH_BANK_INVALID (-900)
#define ERROR_FLASH_SECTOR_INVALID (-901) extern int flash_register_commands(struct command_context_s *cmd_ctx);
#define ERROR_FLASH_OPERATION_FAILED (-902) extern int flash_init_drivers(struct command_context_s *cmd_ctx);
#define ERROR_FLASH_DST_OUT_OF_BANK (-903)
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT (-904) extern int flash_erase_address_range(target_t *target, u32 addr, u32 length);
#define ERROR_FLASH_BUSY (-905) extern int flash_write(target_t *target, image_t *image, u32 *written, int erase);
#define ERROR_FLASH_SECTOR_NOT_ERASED (-906) extern void flash_set_dirty(void);
#define ERROR_FLASH_BANK_NOT_PROBED (-907)
extern flash_bank_t *get_flash_bank_by_num(int num);
#endif /* FLASH_H */ extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
#define ERROR_FLASH_BANK_INVALID (-900)
#define ERROR_FLASH_SECTOR_INVALID (-901)
#define ERROR_FLASH_OPERATION_FAILED (-902)
#define ERROR_FLASH_DST_OUT_OF_BANK (-903)
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT (-904)
#define ERROR_FLASH_BUSY (-905)
#define ERROR_FLASH_SECTOR_NOT_ERASED (-906)
#define ERROR_FLASH_BANK_NOT_PROBED (-907)
#endif /* FLASH_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*************************************************************************** /***************************************************************************
* Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de * * Dominic.Rath@gmx.de *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. * * GNU General Public License for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the * * along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "interpreter.h" #include "interpreter.h"
#include "configuration.h" #include "configuration.h"
#include "binarybuffer.h" #include "binarybuffer.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
var_t *variables = NULL; var_t *variables = NULL;
int handle_var_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_var_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_field_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_field_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int interpreter_register_commands(struct command_context_s *cmd_ctx) int interpreter_register_commands(struct command_context_s *cmd_ctx)
{ {
register_command(cmd_ctx, NULL, "var", handle_var_command, register_command(cmd_ctx, NULL, "var", handle_var_command,
COMMAND_ANY, "allocate, display or delete variable <name> [num_fields|'del'] [size1] ..."); COMMAND_ANY, "allocate, display or delete variable <name> [num_fields|'del'] [size1] ...");
register_command(cmd_ctx, NULL, "field", handle_field_command, register_command(cmd_ctx, NULL, "field", handle_field_command,
COMMAND_ANY, "display/modify variable field <var> <field> [value|'flip']"); COMMAND_ANY, "display/modify variable field <var> <field> [value|'flip']");
register_command(cmd_ctx, NULL, "script", handle_script_command, register_command(cmd_ctx, NULL, "script", handle_script_command,
COMMAND_ANY, "execute commands from <file>"); COMMAND_ANY, "execute commands from <file>");
return ERROR_OK; return ERROR_OK;
} }
var_t* get_var_by_num(int num) var_t* get_var_by_num(int num)
{ {
int count = 0; int count = 0;
var_t *var = variables; var_t *var = variables;
if (var) if (var)
{ {
if (num == count) if (num == count)
return var; return var;
while (var->next) while (var->next)
{ {
var = var->next; var = var->next;
count++; count++;
if (num == count) if (num == count)
return var; return var;
} }
} }
return NULL; return NULL;
} }
var_t* get_var_by_name(char *name) var_t* get_var_by_name(char *name)
{ {
var_t *var = variables; var_t *var = variables;
if (var) if (var)
{ {
if (strcmp(var->name, name) == 0) if (strcmp(var->name, name) == 0)
return var; return var;
while (var->next) while (var->next)
{ {
var = var->next; var = var->next;
if (strcmp(var->name, name) == 0) if (strcmp(var->name, name) == 0)
return var; return var;
} }
} }
return NULL; return NULL;
} }
var_t* get_var_by_namenum(char *namenum) var_t* get_var_by_namenum(char *namenum)
{ {
if ((namenum[0] >= '0') && (namenum[0] <= '9')) if ((namenum[0] >= '0') && (namenum[0] <= '9'))
return get_var_by_num(strtol(namenum, NULL, 0)); return get_var_by_num(strtol(namenum, NULL, 0));
else else
return get_var_by_name(namenum); return get_var_by_name(namenum);
} }
int field_le_to_host(u8 *buffer, void *priv, struct scan_field_s *dummy) int field_le_to_host(u8 *buffer, void *priv, struct scan_field_s *dummy)
{ {
var_field_t *field = priv; var_field_t *field = priv;
field->value = buf_get_u32(buffer, 0, field->num_bits); field->value = buf_get_u32(buffer, 0, field->num_bits);
return ERROR_OK; return ERROR_OK;
} }
int handle_var_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) int handle_var_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{ {
var_t **last_var_p = &variables; var_t **last_var_p = &variables;
int i; int i;
if (argc >= 2) if (argc >= 2)
{ {
while (*last_var_p) while (*last_var_p)
{ {
if (strcmp((*last_var_p)->name, args[0]) == 0) if (strcmp((*last_var_p)->name, args[0]) == 0)
{ {
if (strcmp(args[1], "del") == 0) if (strcmp(args[1], "del") == 0)
{ {
var_t *next = (*last_var_p)->next; var_t *next = (*last_var_p)->next;
free ((*last_var_p)->fields); free ((*last_var_p)->fields);
free (*last_var_p); free (*last_var_p);
*last_var_p = next; *last_var_p = next;
command_print(cmd_ctx, "variable %s deleted", args[0]); command_print(cmd_ctx, "variable %s deleted", args[0]);
} }
else else
command_print(cmd_ctx, "variable of that name already exists"); command_print(cmd_ctx, "variable of that name already exists");
return ERROR_OK; return ERROR_OK;
} }
last_var_p = &((*last_var_p)->next); last_var_p = &((*last_var_p)->next);
} }
if ((args[0][0] >= '0') && (args[0][0] <= '9')) if ((args[0][0] >= '0') && (args[0][0] <= '9'))
{ {
command_print(cmd_ctx, "invalid name specified (first character may not be a number)"); command_print(cmd_ctx, "invalid name specified (first character may not be a number)");
return ERROR_OK; return ERROR_OK;
} }
*last_var_p = malloc(sizeof(var_t)); *last_var_p = malloc(sizeof(var_t));
(*last_var_p)->name = strdup(args[0]); (*last_var_p)->name = strdup(args[0]);
(*last_var_p)->num_fields = argc - 1; (*last_var_p)->num_fields = argc - 1;
(*last_var_p)->next = NULL; (*last_var_p)->next = NULL;
(*last_var_p)->fields = malloc(sizeof(var_field_t) * (*last_var_p)->num_fields); (*last_var_p)->fields = malloc(sizeof(var_field_t) * (*last_var_p)->num_fields);
for (i = 0; i < (*last_var_p)->num_fields; i++) for (i = 0; i < (*last_var_p)->num_fields; i++)
{ {
(*last_var_p)->fields[i].num_bits = strtol(args[1+i], NULL, 0); (*last_var_p)->fields[i].num_bits = strtol(args[1+i], NULL, 0);
(*last_var_p)->fields[i].value = 0x0; (*last_var_p)->fields[i].value = 0x0;
} }
return ERROR_OK; return ERROR_OK;
} }
if (argc == 1) if (argc == 1)
{ {
var_t *var = get_var_by_namenum(args[0]); var_t *var = get_var_by_namenum(args[0]);
if (var) if (var)
{ {
int i; int i;
command_print(cmd_ctx, "%s (%i fields):", var->name, var->num_fields); command_print(cmd_ctx, "%s (%i fields):", var->name, var->num_fields);
for (i = 0; i < (var->num_fields); i++) for (i = 0; i < (var->num_fields); i++)
{ {
command_print(cmd_ctx, "0x%x (/%i)", var->fields[i].value, var->fields[i].num_bits); command_print(cmd_ctx, "0x%x (/%i)", var->fields[i].value, var->fields[i].num_bits);
} }
} }
else else
{ {
command_print(cmd_ctx, "variable %s doesn't exist", args[0]); command_print(cmd_ctx, "variable %s doesn't exist", args[0]);
} }
} }
if (argc == 0) if (argc == 0)
{ {
var_t *var = variables; var_t *var = variables;
int count = 0; int count = 0;
while (var) while (var)
{ {
command_print(cmd_ctx, "%i: %s (%i fields)", count, var->name, var->num_fields); command_print(cmd_ctx, "%i: %s (%i fields)", count, var->name, var->num_fields);
var = var->next; var = var->next;
count++; count++;
} }
} }
return ERROR_OK; return ERROR_OK;
} }
int handle_field_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) int handle_field_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{ {
if (argc < 2) if (argc < 2)
command_print(cmd_ctx, "usage: field <var> <field> [value|'flip']"); return ERROR_COMMAND_SYNTAX_ERROR;
if (argc >= 2) if (argc >= 2)
{ {
var_t *var = get_var_by_namenum(args[0]); var_t *var = get_var_by_namenum(args[0]);
int field_num = strtol(args[1], NULL, 0); int field_num = strtol(args[1], NULL, 0);
if (!var) if (!var)
{ {
command_print(cmd_ctx, "variable %s doesn't exist", args[0]); command_print(cmd_ctx, "variable %s doesn't exist", args[0]);
return ERROR_OK; return ERROR_OK;
} }
if (field_num >= var->num_fields) if (field_num >= var->num_fields)
command_print(cmd_ctx, "variable field %i is out of bounds (max. %i)", field_num, var->num_fields - 1); command_print(cmd_ctx, "variable field %i is out of bounds (max. %i)", field_num, var->num_fields - 1);
if ((var) && (field_num < var->num_fields)) if ((var) && (field_num < var->num_fields))
{ {
if (argc > 2) if (argc > 2)
{ {
if (strcmp(args[2], "flip") == 0) if (strcmp(args[2], "flip") == 0)
var->fields[field_num].value = flip_u32(var->fields[field_num].value, var->fields[field_num].num_bits); var->fields[field_num].value = flip_u32(var->fields[field_num].value, var->fields[field_num].num_bits);
else else
var->fields[field_num].value = strtoul(args[2], NULL, 0); var->fields[field_num].value = strtoul(args[2], NULL, 0);
} }
command_print(cmd_ctx, "%s(%i): 0x%x (/%i)", var->name, field_num, var->fields[field_num].value, var->fields[field_num].num_bits); command_print(cmd_ctx, "%s(%i): 0x%x (/%i)", var->name, field_num, var->fields[field_num].value, var->fields[field_num].num_bits);