diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2010-01-20 10:43:32 -0800 |
---|---|---|
committer | David Brownell <dbrownell@users.sourceforge.net> | 2010-01-20 10:43:32 -0800 |
commit | 6f2b88448fff59d00f625d0d361a7b9abf6bd673 (patch) | |
tree | 1c674b4e7a67de3e08c55d7c1f9351f656e9791d /src/server | |
parent | d036f1700171e0f8056d616a198f17b9be5719e0 (diff) | |
download | openocd+libswd-6f2b88448fff59d00f625d0d361a7b9abf6bd673.tar.gz openocd+libswd-6f2b88448fff59d00f625d0d361a7b9abf6bd673.tar.bz2 openocd+libswd-6f2b88448fff59d00f625d0d361a7b9abf6bd673.tar.xz openocd+libswd-6f2b88448fff59d00f625d0d361a7b9abf6bd673.zip |
gdb_server: correctly report flash sector sizes
Report each region of same-size sectors separately, instead of
incorrectly reporting that every sector has the same size.
This is a longstanding bug on NOR flash chips with non-uniform
sector sizes. It was largely hidden by other bugs in flash
handling. When some of those were recently fixed, this one was
exposed as a regression on str710.
[oyvind.harboe@zylin.com: update the loop to behave on str7 ]
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/gdb_server.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6ed7243d..f3e05759 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1613,22 +1613,6 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len return 0; } -static int gdb_calc_blocksize(struct flash_bank *bank) -{ - uint32_t i; - uint32_t block_size = 0xffffffff; - - /* loop through all sectors and return smallest sector size */ - - for (i = 0; i < (uint32_t)bank->num_sectors; i++) - { - if (bank->sectors[i].size < block_size) - block_size = bank->sectors[i].size; - } - - return block_size; -} - static int compare_bank (const void * a, const void * b) { struct flash_bank *b1, *b2; @@ -1666,7 +1650,6 @@ static int gdb_memory_map(struct connection *connection, int offset; int length; char *separator; - int blocksize; uint32_t ram_start = 0; int i; @@ -1683,6 +1666,7 @@ static int gdb_memory_map(struct connection *connection, * it has no concept of non-cacheable read/write memory (i/o etc). * * FIXME Most non-flash addresses are *NOT* RAM! Don't lie. + * Current versions of GDB assume unlisted addresses are RAM... */ banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count()); @@ -1701,29 +1685,60 @@ static int gdb_memory_map(struct connection *connection, compare_bank); for (i = 0; i < flash_get_bank_count(); i++) { + int j; + unsigned sector_size = 0; + uint32_t start, end; + p = banks[i]; + start = p->base; + end = p->base + p->size; if (ram_start < p->base) xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" " "length=\"0x%x\"/>\n", - ram_start, p->base-ram_start); + ram_start, p->base - ram_start); - /* If device has uneven sector sizes, eg. str7, lpc - * we pass the smallest sector size to gdb memory map - * - * FIXME Don't lie about flash regions with different - * sector sizes; just tell GDB about each region as - * if it were a separate flash device. + /* Report adjacent groups of same-size sectors. So for + * example top boot CFI flash will list an initial region + * with several large sectors (maybe 128KB) and several + * smaller ones at the end (maybe 32KB). STR7 will have + * regions with 8KB, 32KB, and 64KB sectors; etc. */ - blocksize = gdb_calc_blocksize(p); + for (j = 0; j < p->num_sectors; j++) { + unsigned group_len; + + /* Maybe start a new group of sectors. */ + if (sector_size == 0) { + start = p->base + p->sectors[j].offset; + xml_printf(&retval, &xml, &pos, &size, + "<memory type=\"flash\" " + "start=\"0x%x\" ", + start); + sector_size = p->sectors[j].size; + } + + /* Does this finish a group of sectors? + * If not, continue an already-started group. + */ + if (j == p->num_sectors -1) + group_len = (p->base + p->size) - start; + else if (p->sectors[j + 1].size != sector_size) + group_len = p->base + p->sectors[j + 1].offset + - start; + else + continue; + + xml_printf(&retval, &xml, &pos, &size, + "length=\"0x%x\">\n" + "<property name=\"blocksize\">" + "0x%x</property>\n" + "</memory>\n", + group_len, + sector_size); + sector_size = 0; + } - xml_printf(&retval, &xml, &pos, &size, - "<memory type=\"flash\" start=\"0x%x\" " - "length=\"0x%x\">\n" \ - "<property name=\"blocksize\">0x%x</property>\n" \ - "</memory>\n", \ - p->base, p->size, blocksize); ram_start = p->base + p->size; } |