From: David Brownell Date: Sun, 15 Nov 2009 18:35:34 +0000 (-0800) Subject: ARM: memory utils aren't ARM7/ARM9 dependent X-Git-Tag: v0.4.0-rc1~594 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=269040bbad7f18066f5ec5707447c33de6290ef5;p=openocd ARM: memory utils aren't ARM7/ARM9 dependent The arm7_9_checksum_memory() and arm7_9_blank_check_memory() routines are not actually specific to the ARM7 and ARM9 core generations ... they can work for any core which can run algorithms using basic ARM (not Thumb) instructions. Rename them; move the declarations to a more generic site; likewise move the code (and tidy it a bit in the process). NOTE: the blank_check() method falsely returned a success status (0) on one error path, when the algorithm failed. Fixed this bug. Signed-off-by: David Brownell --- diff --git a/src/target/arm720t.c b/src/target/arm720t.c index eb66b120..7bfb97dc 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -535,8 +535,9 @@ struct target_type arm720t_target = .virt2phys = arm720_virt2phys, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 115a1d6b..c35c8252 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2706,156 +2706,6 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t c return retval; } -int arm7_9_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum) -{ - struct working_area *crc_algorithm; - struct armv4_5_algorithm armv4_5_info; - struct reg_param reg_params[2]; - int retval; - - static const uint32_t arm7_9_crc_code[] = { - 0xE1A02000, /* mov r2, r0 */ - 0xE3E00000, /* mov r0, #0xffffffff */ - 0xE1A03001, /* mov r3, r1 */ - 0xE3A04000, /* mov r4, #0 */ - 0xEA00000B, /* b ncomp */ - /* nbyte: */ - 0xE7D21004, /* ldrb r1, [r2, r4] */ - 0xE59F7030, /* ldr r7, CRC32XOR */ - 0xE0200C01, /* eor r0, r0, r1, asl 24 */ - 0xE3A05000, /* mov r5, #0 */ - /* loop: */ - 0xE3500000, /* cmp r0, #0 */ - 0xE1A06080, /* mov r6, r0, asl #1 */ - 0xE2855001, /* add r5, r5, #1 */ - 0xE1A00006, /* mov r0, r6 */ - 0xB0260007, /* eorlt r0, r6, r7 */ - 0xE3550008, /* cmp r5, #8 */ - 0x1AFFFFF8, /* bne loop */ - 0xE2844001, /* add r4, r4, #1 */ - /* ncomp: */ - 0xE1540003, /* cmp r4, r3 */ - 0x1AFFFFF1, /* bne nbyte */ - /* end: */ - 0xEAFFFFFE, /* b end */ - 0x04C11DB7 /* CRC32XOR: .word 0x04C11DB7 */ - }; - - uint32_t i; - - if (target_alloc_working_area(target, sizeof(arm7_9_crc_code), &crc_algorithm) != ERROR_OK) - { - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - - /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(arm7_9_crc_code)/sizeof(uint32_t)); i++) - { - if ((retval = target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), arm7_9_crc_code[i])) != ERROR_OK) - { - return retval; - } - } - - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; - armv4_5_info.core_state = ARMV4_5_STATE_ARM; - - init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - - buf_set_u32(reg_params[0].value, 0, 32, address); - buf_set_u32(reg_params[1].value, 0, 32, count); - - /* 20 second timeout/megabyte */ - int timeout = 20000 * (1 + (count / (1024*1024))); - - if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), timeout, &armv4_5_info)) != ERROR_OK) - { - LOG_ERROR("error executing arm7_9 crc algorithm"); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - target_free_working_area(target, crc_algorithm); - return retval; - } - - *checksum = buf_get_u32(reg_params[0].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - - target_free_working_area(target, crc_algorithm); - - return ERROR_OK; -} - -int arm7_9_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank) -{ - struct working_area *erase_check_algorithm; - struct reg_param reg_params[3]; - struct armv4_5_algorithm armv4_5_info; - int retval; - uint32_t i; - - static const uint32_t erase_check_code[] = - { - /* loop: */ - 0xe4d03001, /* ldrb r3, [r0], #1 */ - 0xe0022003, /* and r2, r2, r3 */ - 0xe2511001, /* subs r1, r1, #1 */ - 0x1afffffb, /* bne loop */ - /* end: */ - 0xeafffffe /* b end */ - }; - - /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) - { - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - - /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint32_t)); i++) - if ((retval = target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t), erase_check_code[i])) != ERROR_OK) - { - return retval; - } - - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; - armv4_5_info.core_state = ARMV4_5_STATE_ARM; - - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - buf_set_u32(reg_params[0].value, 0, 32, address); - - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); - - init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); - - if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &armv4_5_info)) != ERROR_OK) - { - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - target_free_working_area(target, erase_check_algorithm); - return 0; - } - - *blank = buf_get_u32(reg_params[2].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - - target_free_working_area(target, erase_check_algorithm); - - return ERROR_OK; -} - /** * Perform per-target setup that requires JTAG access. */ diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index bbe95ca2..d70bae26 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -143,8 +143,6 @@ int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode) int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer); -int arm7_9_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum); -int arm7_9_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank); int arm7_9_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_prams, struct reg_param *reg_param, uint32_t entry_point, void *arch_info); diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 8be8a125..51fbddfe 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -737,8 +737,9 @@ struct target_type arm7tdmi_target = .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 9aa165c7..fd61020d 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -1407,8 +1407,9 @@ struct target_type arm920t_target = .virt2phys = arm920_virt2phys, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 51b241a5..00b78652 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -864,8 +864,9 @@ struct target_type arm926ejs_target = .read_memory = arm7_9_read_memory, .write_memory = arm926ejs_write_memory, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/arm966e.c b/src/target/arm966e.c index b3d8e158..3b85a5cd 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -261,8 +261,9 @@ struct target_type arm966e_target = .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index 44a978ad..1b7b6452 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -938,8 +938,9 @@ struct target_type arm9tdmi_target = .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index aa05e831..f9b22b94 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -707,6 +707,176 @@ int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_ return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion); } +/** + * Runs ARM code in the target to calculate a CRC32 checksum. + * + * \todo On ARMv5+, rely on BKPT termination for reduced overhead. + */ +int arm_checksum_memory(struct target *target, + uint32_t address, uint32_t count, uint32_t *checksum) +{ + struct working_area *crc_algorithm; + struct armv4_5_algorithm armv4_5_info; + struct reg_param reg_params[2]; + int retval; + uint32_t i; + + static const uint32_t arm_crc_code[] = { + 0xE1A02000, /* mov r2, r0 */ + 0xE3E00000, /* mov r0, #0xffffffff */ + 0xE1A03001, /* mov r3, r1 */ + 0xE3A04000, /* mov r4, #0 */ + 0xEA00000B, /* b ncomp */ + /* nbyte: */ + 0xE7D21004, /* ldrb r1, [r2, r4] */ + 0xE59F7030, /* ldr r7, CRC32XOR */ + 0xE0200C01, /* eor r0, r0, r1, asl 24 */ + 0xE3A05000, /* mov r5, #0 */ + /* loop: */ + 0xE3500000, /* cmp r0, #0 */ + 0xE1A06080, /* mov r6, r0, asl #1 */ + 0xE2855001, /* add r5, r5, #1 */ + 0xE1A00006, /* mov r0, r6 */ + 0xB0260007, /* eorlt r0, r6, r7 */ + 0xE3550008, /* cmp r5, #8 */ + 0x1AFFFFF8, /* bne loop */ + 0xE2844001, /* add r4, r4, #1 */ + /* ncomp: */ + 0xE1540003, /* cmp r4, r3 */ + 0x1AFFFFF1, /* bne nbyte */ + /* end: */ + 0xEAFFFFFE, /* b end */ + /* CRC32XOR: */ + 0x04C11DB7 /* .word 0x04C11DB7 */ + }; + + retval = target_alloc_working_area(target, + sizeof(arm_crc_code), &crc_algorithm); + if (retval != ERROR_OK) + return retval; + + /* convert code into a buffer in target endianness */ + for (i = 0; i < DIM(arm_crc_code); i++) { + retval = target_write_u32(target, + crc_algorithm->address + i * sizeof(uint32_t), + arm_crc_code[i]); + if (retval != ERROR_OK) + return retval; + } + + armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; + armv4_5_info.core_mode = ARMV4_5_MODE_SVC; + armv4_5_info.core_state = ARMV4_5_STATE_ARM; + + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + + buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[1].value, 0, 32, count); + + /* 20 second timeout/megabyte */ + int timeout = 20000 * (1 + (count / (1024 * 1024))); + + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, + crc_algorithm->address, + crc_algorithm->address + sizeof(arm_crc_code) - 8, + timeout, &armv4_5_info); + if (retval != ERROR_OK) { + LOG_ERROR("error executing ARM crc algorithm"); + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + target_free_working_area(target, crc_algorithm); + return retval; + } + + *checksum = buf_get_u32(reg_params[0].value, 0, 32); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + + target_free_working_area(target, crc_algorithm); + + return ERROR_OK; +} + +/** + * Runs ARM code in the target to check whether a memory block holds + * all ones. NOR flash which has been erased, and thus may be written, + * holds all ones. + * + * \todo On ARMv5+, rely on BKPT termination for reduced overhead. + */ +int arm_blank_check_memory(struct target *target, + uint32_t address, uint32_t count, uint32_t *blank) +{ + struct working_area *check_algorithm; + struct reg_param reg_params[3]; + struct armv4_5_algorithm armv4_5_info; + int retval; + uint32_t i; + + static const uint32_t check_code[] = { + /* loop: */ + 0xe4d03001, /* ldrb r3, [r0], #1 */ + 0xe0022003, /* and r2, r2, r3 */ + 0xe2511001, /* subs r1, r1, #1 */ + 0x1afffffb, /* bne loop */ + /* end: */ + 0xeafffffe /* b end */ + }; + + /* make sure we have a working area */ + retval = target_alloc_working_area(target, + sizeof(check_code), &check_algorithm); + if (retval != ERROR_OK) + return retval; + + /* convert code into a buffer in target endianness */ + for (i = 0; i < DIM(check_code); i++) { + retval = target_write_u32(target, + check_algorithm->address + + i * sizeof(uint32_t), + check_code[i]); + if (retval != ERROR_OK) + return retval; + } + + armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; + armv4_5_info.core_mode = ARMV4_5_MODE_SVC; + armv4_5_info.core_state = ARMV4_5_STATE_ARM; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + buf_set_u32(reg_params[0].value, 0, 32, address); + + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + buf_set_u32(reg_params[1].value, 0, 32, count); + + init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); + buf_set_u32(reg_params[2].value, 0, 32, 0xff); + + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + check_algorithm->address, + check_algorithm->address + sizeof(check_code) - 4, + 10000, &armv4_5_info); + if (retval != ERROR_OK) { + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + target_free_working_area(target, check_algorithm); + return retval; + } + + *blank = buf_get_u32(reg_params[2].value, 0, 32); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + + target_free_working_area(target, check_algorithm); + + return ERROR_OK; +} + int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5) { target->arch_info = armv4_5; diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h index 14dfa99e..83b38b65 100644 --- a/src/target/armv4_5.h +++ b/src/target/armv4_5.h @@ -190,6 +190,12 @@ int armv4_5_run_algorithm(struct target *target, int armv4_5_invalidate_core_regs(struct target *target); +int arm_checksum_memory(struct target *target, + uint32_t address, uint32_t count, uint32_t *checksum); +int arm_blank_check_memory(struct target *target, + uint32_t address, uint32_t count, uint32_t *blank); + + /* ARM mode instructions */ @@ -369,7 +375,4 @@ static inline uint32_t mrc_opcode(int cpnum, uint32_t op1, uint32_t op2, uint32_ return t; } - - - #endif /* ARMV4_5_H */ diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index da5e84be..0d00b3aa 100644 --- a/src/target/cortex_a8.c +++ b/src/target/cortex_a8.c @@ -1590,8 +1590,9 @@ struct target_type cortexa8_target = { .read_memory = cortex_a8_read_memory, .write_memory = cortex_a8_write_memory, .bulk_write_memory = cortex_a8_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/cortex_a8.h b/src/target/cortex_a8.h index e7ea6c75..f11d9dda 100644 --- a/src/target/cortex_a8.h +++ b/src/target/cortex_a8.h @@ -32,7 +32,6 @@ #include "register.h" #include "target.h" #include "armv7a.h" -#include "arm7_9_common.h" extern char* cortex_a8_state_strings[]; diff --git a/src/target/fa526.c b/src/target/fa526.c index 9e7b00da..e7c1a2e6 100644 --- a/src/target/fa526.c +++ b/src/target/fa526.c @@ -380,8 +380,9 @@ struct target_type fa526_target = .read_memory = arm920t_read_memory, .write_memory = arm920t_write_memory, .bulk_write_memory = arm7_9_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/feroceon.c b/src/target/feroceon.c index c029e44e..03a5afca 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -696,8 +696,9 @@ struct target_type feroceon_target = .read_memory = arm7_9_read_memory, .write_memory = arm926ejs_write_memory, .bulk_write_memory = feroceon_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, @@ -734,8 +735,9 @@ struct target_type dragonite_target = .read_memory = arm7_9_read_memory, .write_memory = arm7_9_write_memory, .bulk_write_memory = feroceon_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm, diff --git a/src/target/xscale.c b/src/target/xscale.c index 10ccf5dd..0b5b26b3 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -3626,8 +3626,9 @@ struct target_type xscale_target = .read_memory = xscale_read_memory, .write_memory = xscale_write_memory, .bulk_write_memory = xscale_bulk_write_memory, - .checksum_memory = arm7_9_checksum_memory, - .blank_check_memory = arm7_9_blank_check_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, .run_algorithm = armv4_5_run_algorithm,