flash: ROM support

The only reason to define a read-only region is that gdb needs
a complete memory map to choose hard or soft breakpoints properly.

Change-Id: I9d05cb6b91f054ad5cc9333af6b14eb433dbdc99
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/5106
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
Tomas Vanek
2019-04-11 08:29:15 +02:00
committed by Antonio Borneo
parent 3c1bd50217
commit 8ee7cb12cf
8 changed files with 122 additions and 50 deletions

View File

@@ -6178,6 +6178,16 @@ flash bank vbank1 virtual 0x9fc00000 0 0 0 \
@end example @end example
@end deffn @end deffn
@deffn {Flash Driver} read_only
A stub driver without write and erase.
Use to define a ROM region for the gdb memory map.
@example
flash bank $_CHIPNAME.sysrom read_only 0x1ff00000 0xedc0 0 0 \
$_TARGETNAME
@end example
@end deffn
@subsection External Flash @subsection External Flash
@deffn {Flash Driver} {cfi} @deffn {Flash Driver} {cfi}

View File

@@ -60,6 +60,7 @@ NOR_DRIVERS = \
%D%/psoc5lp.c \ %D%/psoc5lp.c \
%D%/psoc6.c \ %D%/psoc6.c \
%D%/qn908x.c \ %D%/qn908x.c \
%D%/read_only.c \
%D%/renesas_rpchf.c \ %D%/renesas_rpchf.c \
%D%/rp2xxx.c \ %D%/rp2xxx.c \
%D%/rsl10.c \ %D%/rsl10.c \

View File

@@ -44,6 +44,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first,
int retval; int retval;
unsigned int num_blocks; unsigned int num_blocks;
if (!bank->driver->protect) {
LOG_ERROR("Flash protection is not supported");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
if (bank->num_prot_blocks) if (bank->num_prot_blocks)
num_blocks = bank->num_prot_blocks; num_blocks = bank->num_prot_blocks;
else else
@@ -59,11 +64,6 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first,
/* force "set" to 0/1 */ /* force "set" to 0/1 */
set = !!set; set = !!set;
if (!bank->driver->protect) {
LOG_ERROR("Flash protection is not supported.");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
/* DANGER! /* DANGER!
* *
* We must not use any cached information about protection state!!!! * We must not use any cached information about protection state!!!!

View File

@@ -84,6 +84,8 @@ struct flash_bank {
target_addr_t base; /**< The base address of this bank */ target_addr_t base; /**< The base address of this bank */
uint32_t size; /**< The size of this chip bank, in bytes */ uint32_t size; /**< The size of this chip bank, in bytes */
bool read_only; /**< a ROM region - mainly to list in gdb memory map */
unsigned int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ unsigned int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */
unsigned int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ unsigned int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */

View File

@@ -292,6 +292,7 @@ extern const struct flash_driver psoc5lp_flash;
extern const struct flash_driver psoc5lp_nvl_flash; extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash; extern const struct flash_driver psoc6_flash;
extern const struct flash_driver qn908x_flash; extern const struct flash_driver qn908x_flash;
extern const struct flash_driver read_only_flash;
extern const struct flash_driver renesas_rpchf_flash; extern const struct flash_driver renesas_rpchf_flash;
extern const struct flash_driver rp2xxx_flash; extern const struct flash_driver rp2xxx_flash;
extern const struct flash_driver rsl10_flash; extern const struct flash_driver rsl10_flash;

View File

@@ -71,6 +71,7 @@ static const struct flash_driver * const flash_drivers[] = {
&psoc5lp_nvl_flash, &psoc5lp_nvl_flash,
&psoc6_flash, &psoc6_flash,
&qn908x_flash, &qn908x_flash,
&read_only_flash,
&renesas_rpchf_flash, &renesas_rpchf_flash,
&rp2xxx_flash, &rp2xxx_flash,
&rsl10_flash, &rsl10_flash,

51
src/flash/nor/read_only.c Normal file
View File

@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 by Tomas Vanek <vanekt@fbl.cz>
*
* To declare a read-only region for GDB memory map.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
FLASH_BANK_COMMAND_HANDLER(rom_bank_command)
{
bank->read_only = true;
return ERROR_OK;
}
static int rom_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
{
LOG_ERROR("Erase of read-only memory refused");
return ERROR_FAIL;
}
static int rom_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
LOG_ERROR("Write to read-only memory refused");
return ERROR_FAIL;
}
static int rom_probe(struct flash_bank *bank)
{
return ERROR_OK;
}
const struct flash_driver read_only_flash = {
.name = "read_only",
.flash_bank_command = rom_bank_command,
.erase = rom_erase,
.write = rom_write,
.read = default_flash_read,
.probe = rom_probe,
.auto_probe = rom_probe,
.erase_check = default_flash_blank_check,
// ROM driver doesn't set driver_priv, free(NULL) makes no harm
.free_driver_priv = default_flash_free_driver_priv,
};

View File

@@ -2004,52 +2004,58 @@ static int gdb_memory_map(struct connection *connection,
"length=\"" TARGET_ADDR_FMT "\"/>\n", "length=\"" TARGET_ADDR_FMT "\"/>\n",
ram_start, p->base - ram_start); ram_start, p->base - ram_start);
/* Report adjacent groups of same-size sectors. So for if (p->read_only) {
* 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.
*/
for (unsigned int j = 0; j < p->num_sectors; j++) {
/* Maybe start a new group of sectors. */
if (sector_size == 0) {
if (p->sectors[j].offset + p->sectors[j].size > p->size) {
LOG_WARNING("The flash sector at offset 0x%08" PRIx32
" overflows the end of %s bank.",
p->sectors[j].offset, p->name);
LOG_WARNING("The rest of bank will not show in gdb memory map.");
break;
}
target_addr_t start;
start = p->base + p->sectors[j].offset;
xml_printf(&retval, &xml, &pos, &size,
"<memory type=\"flash\" "
"start=\"" TARGET_ADDR_FMT "\" ",
start);
sector_size = p->sectors[j].size;
group_len = sector_size;
} else {
group_len += sector_size; /* equal to p->sectors[j].size */
}
/* Does this finish a group of sectors?
* If not, continue an already-started group.
*/
if (j < p->num_sectors - 1
&& p->sectors[j + 1].size == sector_size
&& p->sectors[j + 1].offset == p->sectors[j].offset + sector_size
&& p->sectors[j + 1].offset + p->sectors[j + 1].size <= p->size)
continue;
xml_printf(&retval, &xml, &pos, &size, xml_printf(&retval, &xml, &pos, &size,
"length=\"0x%x\">\n" "<memory type=\"rom\" start=\"" TARGET_ADDR_FMT "\" "
"<property name=\"blocksize\">" "length=\"0x%x\"/>\n",
"0x%x</property>\n" p->base, p->size);
"</memory>\n", } else {
group_len, /* Report adjacent groups of same-size sectors. So for
sector_size); * example top boot CFI flash will list an initial region
sector_size = 0; * 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.
*/
for (unsigned int j = 0; j < p->num_sectors; j++) {
// Maybe start a new group of sectors
if (sector_size == 0) {
if (p->sectors[j].offset + p->sectors[j].size > p->size) {
LOG_WARNING("The flash sector at offset 0x%08" PRIx32
" overflows the end of %s bank.",
p->sectors[j].offset, p->name);
LOG_WARNING("The rest of bank will not show in gdb memory map.");
break;
}
target_addr_t start;
start = p->base + p->sectors[j].offset;
xml_printf(&retval, &xml, &pos, &size,
"<memory type=\"flash\" "
"start=\"" TARGET_ADDR_FMT "\" ",
start);
sector_size = p->sectors[j].size;
group_len = sector_size;
} else {
group_len += sector_size; /* equal to p->sectors[j].size */
}
/* Does this finish a group of sectors?
* If not, continue an already-started group.
*/
if (j < p->num_sectors - 1
&& p->sectors[j + 1].size == sector_size
&& p->sectors[j + 1].offset == p->sectors[j].offset + sector_size
&& p->sectors[j + 1].offset + p->sectors[j + 1].size <= p->size)
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;
}
} }
ram_start = p->base + p->size; ram_start = p->base + p->size;