forked from auracaster/openocd
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:
committed by
Antonio Borneo
parent
3c1bd50217
commit
8ee7cb12cf
@@ -6178,6 +6178,16 @@ flash bank vbank1 virtual 0x9fc00000 0 0 0 \
|
||||
@end example
|
||||
@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
|
||||
|
||||
@deffn {Flash Driver} {cfi}
|
||||
|
||||
@@ -60,6 +60,7 @@ NOR_DRIVERS = \
|
||||
%D%/psoc5lp.c \
|
||||
%D%/psoc6.c \
|
||||
%D%/qn908x.c \
|
||||
%D%/read_only.c \
|
||||
%D%/renesas_rpchf.c \
|
||||
%D%/rp2xxx.c \
|
||||
%D%/rsl10.c \
|
||||
|
||||
@@ -44,6 +44,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first,
|
||||
int retval;
|
||||
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)
|
||||
num_blocks = bank->num_prot_blocks;
|
||||
else
|
||||
@@ -59,11 +64,6 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first,
|
||||
/* force "set" to 0/1 */
|
||||
set = !!set;
|
||||
|
||||
if (!bank->driver->protect) {
|
||||
LOG_ERROR("Flash protection is not supported.");
|
||||
return ERROR_FLASH_OPER_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* DANGER!
|
||||
*
|
||||
* We must not use any cached information about protection state!!!!
|
||||
|
||||
@@ -84,6 +84,8 @@ struct flash_bank {
|
||||
target_addr_t base; /**< The base address of this bank */
|
||||
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 bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */
|
||||
|
||||
|
||||
@@ -292,6 +292,7 @@ extern const struct flash_driver psoc5lp_flash;
|
||||
extern const struct flash_driver psoc5lp_nvl_flash;
|
||||
extern const struct flash_driver psoc6_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 rp2xxx_flash;
|
||||
extern const struct flash_driver rsl10_flash;
|
||||
|
||||
@@ -71,6 +71,7 @@ static const struct flash_driver * const flash_drivers[] = {
|
||||
&psoc5lp_nvl_flash,
|
||||
&psoc6_flash,
|
||||
&qn908x_flash,
|
||||
&read_only_flash,
|
||||
&renesas_rpchf_flash,
|
||||
&rp2xxx_flash,
|
||||
&rsl10_flash,
|
||||
|
||||
51
src/flash/nor/read_only.c
Normal file
51
src/flash/nor/read_only.c
Normal 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,
|
||||
};
|
||||
@@ -2004,52 +2004,58 @@ static int gdb_memory_map(struct connection *connection,
|
||||
"length=\"" TARGET_ADDR_FMT "\"/>\n",
|
||||
ram_start, p->base - ram_start);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
if (p->read_only) {
|
||||
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;
|
||||
"<memory type=\"rom\" start=\"" TARGET_ADDR_FMT "\" "
|
||||
"length=\"0x%x\"/>\n",
|
||||
p->base, p->size);
|
||||
} else {
|
||||
/* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user