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