Add a mandatory field in struct arm7_9_common for regular, non-optimized
memory writes. Together with the existing bulk_memory_write field, this
allows variants to select any combination of implementations for regular
and bulk writes, without risking infinite loops from accidentally using
bulk writes for implementing bulk writes.
ARM 7/9 targets may now select arm7_9_memory_write_opt as their
target.write_memory implementation, which will dispatch to
arm7_9_common.bulk_write_memory if possible, or fallback to
arm7_9_common.write_memory otherwise.
To avoid loops, bulk write implementations mustn't call any other
functions than arm7_9_write_memory_no_opt() to write memory; it will
unconditionally call arm7_9_common.write_memory. If they fail, they should
simply return error to allow the caller to fallback to regular writes.
Tested on a regular ARM7TDMI only.
Change-Id: Iae42a6e093e2df68c4823c927d757ae8f42ef388
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/1685
Tested-by: jenkins
Reviewed-by: Sergey A. Borshch <sb-sf@users.sourceforge.net>
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
const uint8_t *buffer)
{
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
const uint8_t *buffer)
{
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- if (size == 4 && count > 32 && arm7_9->bulk_write_memory)
- return arm7_9->bulk_write_memory(target, address, count, buffer);
- else
- return arm7_9_write_memory(target, address, size, count, buffer);
+ if (size == 4 && count > 32 && arm7_9->bulk_write_memory) {
+ /* Attempt to do a bulk write */
+ retval = arm7_9->bulk_write_memory(target, address, count, buffer);
+
+ if (retval == ERROR_OK)
+ return ERROR_OK;
+ }
+
+ return arm7_9->write_memory(target, address, size, count, buffer);
+}
+
+int arm7_9_write_memory_no_opt(struct target *target,
+ uint32_t address,
+ uint32_t size,
+ uint32_t count,
+ const uint8_t *buffer)
+{
+ struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
+
+ return arm7_9->write_memory(target, address, size, count, buffer);
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
int i;
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
int i;
+ if (address % 4 != 0)
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+
if (!arm7_9->dcc_downloads)
if (!arm7_9->dcc_downloads)
- return target_write_memory(target, address, 4, count, buffer);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
/* regrab previously allocated working_area, or allocate a new one */
if (!arm7_9->dcc_working_area) {
/* regrab previously allocated working_area, or allocate a new one */
if (!arm7_9->dcc_working_area) {
/* make sure we have a working area */
if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) {
LOG_INFO("no working area available, falling back to memory writes");
/* make sure we have a working area */
if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) {
LOG_INFO("no working area available, falling back to memory writes");
- return target_write_memory(target, address, 4, count, buffer);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* copy target instructions to target endianness */
for (i = 0; i < 6; i++)
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
}
/* copy target instructions to target endianness */
for (i = 0; i < 6; i++)
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
- /* write DCC code to working area */
- retval = target_write_memory(target,
+ /* write DCC code to working area, using the non-optimized
+ * memory write to avoid ending up here again */
+ retval = arm7_9_write_memory_no_opt(target,
arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
if (retval != ERROR_OK)
return retval;
arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
if (retval != ERROR_OK)
return retval;
void (*pre_restore_context)(struct target *target);
/**< Callback function called before restoring the processor context */
void (*pre_restore_context)(struct target *target);
/**< Callback function called before restoring the processor context */
+ /**
+ * Variant specific memory write function that does not dispatch to bulk_write_memory.
+ * Used as a fallback when bulk writes are unavailable, or for writing data needed to
+ * do the bulk writes.
+ */
+ int (*write_memory)(struct target *target, uint32_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer);
/**
* Write target memory in multiples of 4 bytes, optimized for
* writing large quantities of data.
/**
* Write target memory in multiples of 4 bytes, optimized for
* writing large quantities of data.
uint32_t size, uint32_t count, const uint8_t *buffer);
int arm7_9_write_memory_opt(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer);
uint32_t size, uint32_t count, const uint8_t *buffer);
int arm7_9_write_memory_opt(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer);
+int arm7_9_write_memory_no_opt(struct target *target, uint32_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer);
int arm7_9_bulk_write_memory(struct target *target, uint32_t address,
uint32_t count, const uint8_t *buffer);
int arm7_9_bulk_write_memory(struct target *target, uint32_t address,
uint32_t count, const uint8_t *buffer);
arm7_9->enable_single_step = arm7_9_enable_eice_step;
arm7_9->disable_single_step = arm7_9_disable_eice_step;
arm7_9->enable_single_step = arm7_9_enable_eice_step;
arm7_9->disable_single_step = arm7_9_disable_eice_step;
+ arm7_9->write_memory = arm7_9_write_memory;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
-int arm920t_write_memory_opt(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (size == 4 && count > 32 && arm7_9->bulk_write_memory)
- return arm7_9->bulk_write_memory(target, address, count, buffer);
- else
- return arm920t_write_memory(target, address, size, count, buffer);
-}
-
/* EXPORTED to FA256 */
int arm920t_soft_reset_halt(struct target *target)
{
/* EXPORTED to FA256 */
int arm920t_soft_reset_halt(struct target *target)
{
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm920t_read_memory,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm920t_read_memory,
- .write_memory = arm920t_write_memory_opt,
+ .write_memory = arm7_9_write_memory_opt,
.read_phys_memory = arm920t_read_phys_memory,
.write_phys_memory = arm920t_write_phys_memory,
.mmu = arm920_mmu,
.read_phys_memory = arm920t_read_phys_memory,
.write_phys_memory = arm920t_write_phys_memory,
.mmu = arm920_mmu,
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
int arm920t_write_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
int arm920t_write_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm920t_write_memory_opt(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
int arm920t_post_debug_entry(struct target *target);
void arm920t_pre_restore_context(struct target *target);
int arm920t_get_ttb(struct target *target, uint32_t *result);
int arm920t_post_debug_entry(struct target *target);
void arm920t_pre_restore_context(struct target *target);
int arm920t_get_ttb(struct target *target, uint32_t *result);
-int arm926ejs_write_memory_opt(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (size == 4 && count > 32 && arm7_9->bulk_write_memory)
- return arm7_9->bulk_write_memory(target, address, count, buffer);
- else
- return arm926ejs_write_memory(target, address, size, count, buffer);
-}
-
static int arm926ejs_write_phys_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, const uint8_t *buffer)
static int arm926ejs_write_phys_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, const uint8_t *buffer)
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
- .write_memory = arm926ejs_write_memory_opt,
+ .write_memory = arm7_9_write_memory_opt,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
int arm926ejs_arch_state(struct target *target);
int arm926ejs_write_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
int arm926ejs_arch_state(struct target *target);
int arm926ejs_write_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm926ejs_write_memory_opt(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
int arm926ejs_soft_reset_halt(struct target *target);
extern const struct command_registration arm926ejs_command_handlers[];
int arm926ejs_soft_reset_halt(struct target *target);
extern const struct command_registration arm926ejs_command_handlers[];
arm7_9->enable_single_step = arm9tdmi_enable_single_step;
arm7_9->disable_single_step = arm9tdmi_disable_single_step;
arm7_9->enable_single_step = arm9tdmi_enable_single_step;
arm7_9->disable_single_step = arm9tdmi_disable_single_step;
+ arm7_9->write_memory = arm7_9_write_memory;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
arm7_9->enable_single_step = arm9tdmi_enable_single_step;
arm7_9->disable_single_step = arm9tdmi_disable_single_step;
arm7_9->enable_single_step = arm9tdmi_enable_single_step;
arm7_9->disable_single_step = arm9tdmi_disable_single_step;
+ arm7_9->write_memory = arm920t_write_memory;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
arm7_9->post_debug_entry = NULL;
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm920t_read_memory,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm920t_read_memory,
- .write_memory = arm920t_write_memory_opt,
+ .write_memory = arm7_9_write_memory_opt,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
uint32_t dcc_size = sizeof(dcc_code);
uint32_t dcc_size = sizeof(dcc_code);
+ if (address % 4 != 0)
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+
if (!arm7_9->dcc_downloads)
if (!arm7_9->dcc_downloads)
- return target_write_memory(target, address, 4, count, buffer);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
/* regrab previously allocated working_area, or allocate a new one */
if (!arm7_9->dcc_working_area) {
/* regrab previously allocated working_area, or allocate a new one */
if (!arm7_9->dcc_working_area) {
/* make sure we have a working area */
if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
LOG_INFO("no working area available, falling back to memory writes");
/* make sure we have a working area */
if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
LOG_INFO("no working area available, falling back to memory writes");
- return target_write_memory(target, address, 4, count, buffer);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* copy target instructions to target endianness */
for (i = 0; i < dcc_size/4; i++)
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
}
/* copy target instructions to target endianness */
for (i = 0; i < dcc_size/4; i++)
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
- /* write DCC code to working area */
- retval = target_write_memory(target,
+ /* write DCC code to working area, using the non-optimized
+ * memory write to avoid ending up here again */
+ retval = arm7_9_write_memory_no_opt(target,
arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
if (retval != ERROR_OK)
return retval;
arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
if (retval != ERROR_OK)
return retval;
arm926ejs_init_arch_info(target, arm926ejs, target->tap);
feroceon_common_setup(target);
arm926ejs_init_arch_info(target, arm926ejs, target->tap);
feroceon_common_setup(target);
+ struct arm *arm = target->arch_info;
+ struct arm7_9_common *arm7_9 = arm->arch_info;
+ arm7_9->write_memory = arm926ejs_write_memory;
+
/* the standard ARM926 methods don't always work (don't ask...) */
arm926ejs->read_cp15 = feroceon_read_cp15;
arm926ejs->write_cp15 = feroceon_write_cp15;
/* the standard ARM926 methods don't always work (don't ask...) */
arm926ejs->read_cp15 = feroceon_read_cp15;
arm926ejs->write_cp15 = feroceon_write_cp15;
arm966e_init_arch_info(target, arm966e, target->tap);
feroceon_common_setup(target);
arm966e_init_arch_info(target, arm966e, target->tap);
feroceon_common_setup(target);
+ struct arm *arm = target->arch_info;
+ struct arm7_9_common *arm7_9 = arm->arch_info;
+ arm7_9->write_memory = arm7_9_write_memory;
+
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
- .write_memory = arm926ejs_write_memory_opt,
+ .write_memory = arm7_9_write_memory_opt,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)