extern flash_driver_t stellaris_flash;
extern flash_driver_t str9xpec_flash;
extern flash_driver_t stm32x_flash;
+extern flash_driver_t tms470_flash;
flash_driver_t *flash_drivers[] =
{
&stellaris_flash,
&str9xpec_flash,
&stm32x_flash,
+ &tms470_flash,
NULL,
};
{
flash_cmd = register_command(cmd_ctx, NULL, "flash", NULL, COMMAND_ANY, NULL);
- register_command(cmd_ctx, flash_cmd, "bank", handle_flash_bank_command, COMMAND_CONFIG, NULL);
-
+ register_command(cmd_ctx, flash_cmd, "bank", handle_flash_bank_command, COMMAND_CONFIG, "flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
+ register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_ANY,
+ "auto erase flash sectors <on|off>");
return ERROR_OK;
}
-int flash_init(struct command_context_s *cmd_ctx)
+int flash_init_drivers(struct command_context_s *cmd_ctx)
{
if (flash_banks)
{
"write_image <file> [offset] [type]");
register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
"set protection of sectors at <bank> <first> <last> <on|off>");
- register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_EXEC,
- "auto erase flash sectors <on|off>");
}
return ERROR_OK;
}
-flash_bank_t *get_flash_bank_by_num(int num)
+flash_bank_t *get_flash_bank_by_num_noprobe(int num)
{
flash_bank_t *p;
int i = 0;
return NULL;
}
-/* flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]
- */
+flash_bank_t *get_flash_bank_by_num(int num)
+{
+ flash_bank_t *p = get_flash_bank_by_num_noprobe(num);
+ int retval;
+
+ if (p == NULL)
+ return NULL;
+
+ retval = p->driver->auto_probe(p);
+
+ if (retval != ERROR_OK)
+ {
+ ERROR("auto_probe failed %d\n", retval);
+ return NULL;
+ }
+ return p;
+}
+
int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
int i;
if (argc < 6)
{
- WARNING("incomplete flash_bank configuration");
- WARNING("flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
- return ERROR_OK;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if ((target = get_target_by_num(strtoul(args[5], NULL, 0))) == NULL)
{
char buf[1024];
+ /* attempt auto probe */
+ p->driver->auto_probe(p);
+
command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
i, p->driver->name, p->base, p->size, p->bus_width, p->chip_width);
for (j = 0; j < p->num_sectors; j++)
return ERROR_OK;
}
- p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+ p = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0));
if (p)
{
if ((retval = p->driver->probe(p)) == ERROR_OK)
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)
+ if ((retval = flash_erase_address_range(target, address, length)) != ERROR_OK)
{
switch (retval)
{
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)
{
/* cycle through bank list */
for (c = flash_banks; c; c = c->next)
{
+ int retval;
+ retval = c->driver->auto_probe(c);
+
+ if (retval != ERROR_OK)
+ {
+ ERROR("auto_probe failed %d\n", retval);
+ return NULL;
+ }
/* check whether address belongs to this flash bank */
if ((addr >= c->base) && (addr < c->base + c->size) && target == c->target)
return c;
}
/* erase given flash region, selects proper bank according to target and address */
-int flash_erase(target_t *target, u32 addr, u32 length)
+int flash_erase_address_range(target_t *target, u32 addr, u32 length)
{
flash_bank_t *c;
int first = -1;
int section;
u32 section_offset;
-
+ flash_bank_t *c;
+
section = 0;
section_offset = 0;
if (failed != NULL)
for (i = 0; i < image->num_sections; i++)
failed[i] = 0;
-
+
+ if (erase)
+ {
+ /* assume all sectors need erasing - stops any problems
+ * when flash_write is called multiple times */
+
+ flash_set_dirty();
+ }
+
/* loop until we reach end of the image */
while (section < image->num_sections)
{
- flash_bank_t *c;
u32 buffer_size;
u8 *buffer;
int section_first;
if (erase)
{
/* calculate and erase sectors */
- retval = flash_erase( target, run_address, run_size );
+ retval = flash_erase_address_range( target, run_address, run_size );
}
if (retval == ERROR_OK)