Commit 237e8948 authored by drath's avatar drath
Browse files

- split fileio handling into fileio part and image handling

- reworked etm/etb into a generic etm part with trace capture drivers (currently only etb supported)
- added XScale debug handler binary to repository
- added Thumb disassembling (thanks to Vincent Palatin for this patch)
- added support for non-CFI compatible flashes to cfi driver (currently only SST39VFxxx devices supported)
This checkin is experimental, not suitable for general use


git-svn-id: svn://svn.berlios.de/openocd/trunk@155 b42882b7-edfa-0310-969c-e2dbd0fdcd60
parent e8af4de0
INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target $(all_includes)
METASOURCES = AUTO
noinst_LIBRARIES = libflash.a
libflash_a_SOURCES = flash.c lpc2000.c cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c
noinst_HEADERS = flash.h lpc2000.h cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h
libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c
noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h
This diff is collapsed.
......@@ -30,10 +30,12 @@ typedef struct cfi_flash_bank_s
working_area_t *erase_check_algorithm;
int x16_as_x8;
int jedec_probe;
int not_cfi;
u16 manufacturer;
u16 device_id;
char qry[3];
/* identification string */
......@@ -108,6 +110,8 @@ typedef struct cfi_spansion_pri_ext_s
u8 VppMax;
u8 TopBottom;
int _reversed_geometry;
u32 _unlock1;
u32 _unlock2;
} cfi_spansion_pri_ext_t;
/* Atmel primary extended query table as defined for and used by
......@@ -124,6 +128,17 @@ typedef struct cfi_atmel_pri_ext_s
u8 page_mode;
} cfi_atmel_pri_ext_t;
enum {
CFI_UNLOCK_555_2AA,
CFI_UNLOCK_5555_2AAA,
};
typedef struct cfi_unlock_addresses_s
{
u32 unlock1;
u32 unlock2;
} cfi_unlock_addresses_t;
typedef struct cfi_fixup_s
{
u16 mfr;
......@@ -135,6 +150,7 @@ typedef struct cfi_fixup_s
#define CFI_MFR_AMD 0x0001
#define CFI_MFR_ATMEL 0x001F
#define CFI_MFR_ST 0x0020 /* STMicroelectronics */
#define CFI_MFR_SST 0x00BF
#define CFI_MFR_ANY 0xffff
#define CFI_ID_ANY 0xffff
......
......@@ -35,6 +35,7 @@
#include <errno.h>
#include <fileio.h>
#include <image.h>
/* command handlers */
int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
......@@ -493,9 +494,7 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
u8 *buffer;
u32 buf_cnt;
fileio_t file;
fileio_image_t image_info;
enum fileio_sec_type sec_type;
image_t image;
duration_t duration;
char *duration_text;
......@@ -511,7 +510,12 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
duration_start_measure(&duration);
fileio_identify_image_type(&sec_type, (argc == 4) ? args[3] : NULL);
identify_image_type(&image.type, (argc == 4) ? args[3] : NULL);
image.base_address_set = 1;
image.base_address = strtoul(args[1], NULL, 0);
image.start_address_set = 0;
offset = strtoul(args[2], NULL, 0);
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
......@@ -521,20 +525,16 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
return ERROR_OK;
}
image_info.base_address = strtoul(args[2], NULL, 0);
image_info.has_start_address = 0;
if (fileio_open(&file, args[1], FILEIO_READ,
FILEIO_IMAGE, &image_info, sec_type) != ERROR_OK)
if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
{
command_print(cmd_ctx, "flash write error: %s", file.error_str);
command_print(cmd_ctx, "flash write error: %s", image.error_str);
return ERROR_OK;
}
binary_size = file.size;
binary_size = image.size;
buffer = malloc(binary_size);
fileio_read(&file, binary_size, buffer, &buf_cnt);
image_read(&image, binary_size, buffer, &buf_cnt);
if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK)
{
......@@ -571,12 +571,12 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
{
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "wrote file %s to flash bank %i at offset 0x%8.8x in %s",
file.url, strtoul(args[0], NULL, 0), offset, duration_text);
args[1], strtoul(args[0], NULL, 0), offset, duration_text);
free(duration_text);
}
free(buffer);
fileio_close(&file);
image_close(&image);
return ERROR_OK;
}
......@@ -38,6 +38,7 @@
#include "flash.h"
#include "time_support.h"
#include "fileio.h"
#include "image.h"
int nand_register_commands(struct command_context_s *cmd_ctx);
int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
......@@ -1163,10 +1164,8 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
u32 buf_cnt;
enum oob_formats oob_format = NAND_OOB_NONE;
fileio_t file;
fileio_image_t image_info;
int sec_type_identified = 0;
enum fileio_sec_type sec_type;
image_t image;
int image_type_identified = 0;
duration_t duration;
char *duration_text;
......@@ -1201,9 +1200,9 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY;
else
{
if (fileio_identify_image_type(&sec_type, args[i]) == ERROR_OK)
if (identify_image_type(&image.type, args[i]) == ERROR_OK)
{
sec_type_identified = 1;
image_type_identified = 1;
}
else
{
......@@ -1214,27 +1213,27 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
}
/* if no image type option was encountered, set the default */
if (!sec_type_identified)
if (!image_type_identified)
{
fileio_identify_image_type(&sec_type, NULL);
sec_type_identified = 1;
identify_image_type(&image.type, NULL);
image_type_identified = 1;
}
image_info.base_address = strtoul(args[2], NULL, 0);
image_info.has_start_address = 0;
image.base_address_set = 1;
image.base_address = strtoul(args[2], NULL, 0);
image.start_address_set = 0;
if (fileio_open(&file, args[1], FILEIO_READ,
FILEIO_IMAGE, &image_info, sec_type) != ERROR_OK)
if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
{
command_print(cmd_ctx, "flash write error: %s", file.error_str);
command_print(cmd_ctx, "flash write error: %s", image.error_str);
return ERROR_OK;
}
/* the offset might have been overwritten by the image base address */
offset = image_info.base_address;
offset = image.base_address;
buf_cnt = binary_size = file.size;
buf_cnt = binary_size = image.size;
if (!(oob_format & NAND_OOB_ONLY))
{
......@@ -1263,7 +1262,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (page)
{
fileio_read(&file, page_size, page, &size_read);
image_read(&image, page_size, page, &size_read);
buf_cnt -= size_read;
if (size_read < page_size)
{
......@@ -1273,7 +1272,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (oob)
{
fileio_read(&file, oob_size, oob, &size_read);
image_read(&image, oob_size, oob, &size_read);
buf_cnt -= size_read;
if (size_read < oob_size)
{
......@@ -1284,7 +1283,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (nand_write_page(p, offset / p->page_size, page, page_size, oob, oob_size) != ERROR_OK)
{
command_print(cmd_ctx, "failed writing file %s to NAND flash %s at offset 0x%8.8x",
file.url, args[0], offset);
args[1], args[0], offset);
return ERROR_OK;
}
offset += page_size;
......@@ -1292,7 +1291,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s",
file.url, args[0], image_info.base_address, duration_text);
args[1], args[0], image.base_address, duration_text);
free(duration_text);
}
else
......@@ -1318,8 +1317,7 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
{
if (p->device)
{
fileio_t file;
fileio_image_t image_info;
fileio_t fileio;
duration_t duration;
char *duration_text;
int retval;
......@@ -1367,14 +1365,10 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
oob_size = 64;
oob = malloc(oob_size);
}
image_info.base_address = address;
image_info.has_start_address = 0;
if (fileio_open(&file, args[1], FILEIO_WRITE,
FILEIO_IMAGE, &image_info, FILEIO_PLAIN) != ERROR_OK)
if (fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
{
command_print(cmd_ctx, "dump_image error: %s", file.error_str);
command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);
return ERROR_OK;
}
......@@ -1391,13 +1385,13 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
if (page)
{
fileio_write(&file, page_size, page, &size_written);
fileio_write(&fileio, page_size, page, &size_written);
bytes_done += page_size;
}
if (oob)
{
fileio_write(&file, oob_size, oob, &size_written);
fileio_write(&fileio, oob_size, oob, &size_written);
bytes_done += oob_size;
}
......@@ -1411,10 +1405,10 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
if (oob)
free(oob);
fileio_close(&file);
fileio_close(&fileio);
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "dumped %lli byte in %s", file.size, duration_text);
command_print(cmd_ctx, "dumped %lli byte in %s", fileio.size, duration_text);
free(duration_text);
}
else
......
/***************************************************************************
* Copyright (C) 2007 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 <stdlib.h>
#include "log.h"
#include "flash.h"
#include "cfi.h"
#include "non_cfi.h"
/* non-CFI compatible flashes */
non_cfi_t non_cfi_flashes[] = {
{
.mfr = CFI_MFR_SST,
.id = 0xd4,
.pri_id = 0x02,
.dev_size = 0x10,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010000f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd5,
.pri_id = 0x02,
.dev_size = 0x11,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010001f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd6,
.pri_id = 0x02,
.dev_size = 0x12,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010003f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd7,
.pri_id = 0x02,
.dev_size = 0x13,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010007f,
0x00000000
}
},
{
.mfr = 0,
.id = 0,
}
};
void cfi_fixup_non_cfi(flash_bank_t *bank, void *param)
{
cfi_flash_bank_t *cfi_info = bank->driver_priv;
non_cfi_t *non_cfi = non_cfi_flashes;
while (non_cfi->mfr)
{
if ((cfi_info->manufacturer == non_cfi->mfr)
&& (cfi_info->device_id == non_cfi->id))
{
break;
}
non_cfi++;
}
cfi_info->not_cfi = 1;
/* fill in defaults for non-critical data */
cfi_info->vcc_min = 0x0;
cfi_info->vcc_max = 0x0;
cfi_info->vpp_min = 0x0;
cfi_info->vpp_max = 0x0;
cfi_info->word_write_timeout_typ = 0x0;
cfi_info->buf_write_timeout_typ = 0x0;
cfi_info->block_erase_timeout_typ = 0x0;
cfi_info->chip_erase_timeout_typ = 0x0;
cfi_info->word_write_timeout_max = 0x0;
cfi_info->buf_write_timeout_max = 0x0;
cfi_info->block_erase_timeout_max = 0x0;
cfi_info->chip_erase_timeout_max = 0x0;
cfi_info->qry[0] = 'Q';
cfi_info->qry[1] = 'R';
cfi_info->qry[2] = 'Y';
cfi_info->pri_id = non_cfi->pri_id;
cfi_info->pri_addr = 0x0;
cfi_info->alt_id = 0x0;
cfi_info->alt_addr = 0x0;
cfi_info->alt_ext = NULL;
cfi_info->interface_desc = non_cfi->interface_desc;
cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
cfi_info->num_erase_regions = non_cfi->num_erase_regions;
cfi_info->erase_region_info = non_cfi->erase_region_info;
if (cfi_info->pri_id == 0x2)
{
cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));
pri_ext->pri[0] = 'P';
pri_ext->pri[1] = 'R';
pri_ext->pri[2] = 'I';
pri_ext->major_version = '1';
pri_ext->minor_version = '0';
pri_ext->SiliconRevision = 0x0;
pri_ext->EraseSuspend = 0x0;
pri_ext->EraseSuspend = 0x0;
pri_ext->BlkProt = 0x0;
pri_ext->TmpBlkUnprotect = 0x0;
pri_ext->BlkProtUnprot = 0x0;
pri_ext->SimultaneousOps = 0x0;
pri_ext->BurstMode = 0x0;
pri_ext->PageMode = 0x0;
pri_ext->VppMin = 0x0;
pri_ext->VppMax = 0x0;
pri_ext->TopBottom = 0x0;
pri_ext->_reversed_geometry = 0;
cfi_info->pri_ext = pri_ext;
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
{
ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
exit(-1);
}
}
/***************************************************************************
* Copyright (C) 2007 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 NON_CFI_H
#define NON_CFI_H
#include "types.h"
typedef struct non_cfi_s
{
u16 mfr;
u16 id;
u16 pri_id;
u8 dev_size;
u16 interface_desc;
u16 max_buf_write_size;
u8 num_erase_regions;
u32 erase_region_info[6];
} non_cfi_t;
extern non_cfi_t non_cfi_flashes[];
extern void cfi_fixup_non_cfi(flash_bank_t *bank, void *param);
#endif /* NON_CFI_H */
......@@ -98,7 +98,7 @@ int fileio_open_local(fileio_t *fileio)
}
}
if (fileio->pri_type == FILEIO_IMAGE)
if (fileio->type == FILEIO_BINARY)
strcat(access, "b");
if (!(fileio_local->file = fopen(fileio->url, access)))
......@@ -120,126 +120,7 @@ int fileio_open_local(fileio_t *fileio)
return ERROR_OK;
}
//#ifdef FILEIO_BUFFER_COMPLETE_IHEX
int fileio_ihex_buffer_complete(fileio_t *fileio)
{
fileio_image_t *image = fileio->pri_type_private;
fileio_ihex_t *ihex = fileio->sec_type_private;
u32 raw_bytes_read, raw_bytes;
int retval;
u32 full_address = image->base_address;
char *buffer = malloc(ihex->raw_size);
u32 cooked_bytes = 0x0;
ihex->raw_size = fileio->size;
ihex->buffer = malloc(ihex->raw_size >> 1);
if ((retval = fileio_dispatch_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
{
free(buffer);
ERROR("failed buffering IHEX file, read failed");
return ERROR_FILEIO_OPERATION_FAILED;
}
if (raw_bytes_read != ihex->raw_size)
{
free(buffer);
ERROR("failed buffering complete IHEX file, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
}
raw_bytes = 0x0;
while (raw_bytes < raw_bytes_read)
{
u32 count;
u32 address;
u32 record_type;
u32 checksum;
if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
{
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid IHEX record");
return ERROR_FILEIO_OPERATION_FAILED;
}
raw_bytes += 9;
if (record_type == 0)
{
if ((full_address & 0xffff) != address)
{
free(buffer);
ERROR("can't handle non-linear IHEX file");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
return ERROR_FILEIO_OPERATION_FAILED;
}
while (count-- > 0)
{
sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
raw_bytes += 2;
cooked_bytes += 1;
full_address++;
}
}
else if (record_type == 1)
{
free(buffer);
fileio->size = cooked_bytes;
return ERROR_OK;
}
else if (record_type == 4)
{
u16 upper_address;
sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
raw_bytes += 4;
if ((full_address >> 16) != upper_address)
{
free(buffer);
ERROR("can't handle non-linear IHEX file");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
return ERROR_FILEIO_OPERATION_FAILED;
}
}
else if (record_type == 5)
{
u32 start_address;
sscanf(&buffer[raw_bytes], "%8x", &start_address);
raw_bytes += 8;
image->has_start_address = 1;
image->start_address = be_to_h_u32((u8*)&start_address);
}
else
{
free(buffer);
ERROR("unhandled IHEX record type: %i", record_type);
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "unhandled IHEX record type: %i", record_type);
return ERROR_FILEIO_OPERATION_FAILED;
}
sscanf(&buffer[raw_bytes], "%2x", &checksum);
raw_bytes += 2;
/* consume new-line character(s) */