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 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}
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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!!!!
|
||||||
|
|||||||
@@ -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) */
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
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",
|
"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;
|
||||||
|
|||||||
Reference in New Issue
Block a user