target: don't implicitly include "algorithm.h"
[openocd.git] / src / target / armv4_5.c
index f7d5d16c3ac97d9c038d9192e4818bdb0f0ec950..e6e0bd7e355c53752452e5c4c7af26e9f1f6419f 100644 (file)
 #endif
 
 #include "armv4_5.h"
+#include "breakpoints.h"
 #include "arm_disassembler.h"
 #include "binarybuffer.h"
+#include "algorithm.h"
 
 
-struct bitfield_desc armv4_5_psr_bitfield_desc[] =
-{
-       {"M[4:0]", 5},
-       {"T", 1},
-       {"F", 1},
-       {"I", 1},
-       {"reserved", 16},
-       {"J", 1},
-       {"reserved", 2},
-       {"Q", 1},
-       {"V", 1},
-       {"C", 1},
-       {"Z", 1},
-       {"N", 1},
-};
-
 char* armv4_5_core_reg_list[] =
 {
        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
@@ -157,14 +143,26 @@ uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 struct reg armv4_5_gdb_dummy_fp_reg =
 {
-       "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
+       .name = "GDB dummy floating-point register",
+       .value = armv4_5_gdb_dummy_fp_value,
+       .dirty = 0,
+       .valid = 1,
+       .size = 96,
+       .arch_info = NULL,
+       .arch_type = 0,
 };
 
 uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
 
 struct reg armv4_5_gdb_dummy_fps_reg =
 {
-       "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
+       .name = "GDB dummy floating-point status register",
+       .value = armv4_5_gdb_dummy_fps_value,
+       .dirty = 0,
+       .valid = 1,
+       .size = 32,
+       .arch_info = NULL,
+       .arch_type = 0,
 };
 
 int armv4_5_get_core_reg(struct reg *reg)
@@ -278,8 +276,6 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
                reg_list[i].value = calloc(1, 4);
                reg_list[i].dirty = 0;
                reg_list[i].valid = 0;
-               reg_list[i].bitfield_desc = NULL;
-               reg_list[i].num_bitfields = 0;
                reg_list[i].arch_type = armv4_5_core_reg_arch_type;
                reg_list[i].arch_info = &arch_info[i];
        }
@@ -464,7 +460,7 @@ usage:
 
 int armv4_5_register_commands(struct command_context *cmd_ctx)
 {
-       command_t *armv4_5_cmd;
+       struct command *armv4_5_cmd;
 
        armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5",
                        NULL, COMMAND_ANY,
@@ -713,6 +709,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(&reg_params[0], "r0", 32, PARAM_IN_OUT);
+       init_reg_param(&reg_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(&reg_params[0]);
+               destroy_reg_param(&reg_params[1]);
+               target_free_working_area(target, crc_algorithm);
+               return retval;
+       }
+
+       *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_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(&reg_params[0], "r0", 32, PARAM_OUT);
+       buf_set_u32(reg_params[0].value, 0, 32, address);
+
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       buf_set_u32(reg_params[1].value, 0, 32, count);
+
+       init_reg_param(&reg_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(&reg_params[0]);
+               destroy_reg_param(&reg_params[1]);
+               destroy_reg_param(&reg_params[2]);
+               target_free_working_area(target, check_algorithm);
+               return retval;
+       }
+
+       *blank = buf_get_u32(reg_params[2].value, 0, 32);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_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;

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)