armv7m: Integrate build of checksum code
[openocd.git] / src / target / armv7m.c
index 771613981e90193208785c7f76c860da264ed645..8432a419a752f4a9227049043b9f3feceb69e1f5 100644 (file)
@@ -44,7 +44,7 @@
 #define _DEBUG_INSTRUCTION_EXECUTION_
 #endif
 
-static char *armv7m_exception_strings[] = {
+static const char * const armv7m_exception_strings[] = {
        "", "Reset", "NMI", "HardFault",
        "MemManage", "BusFault", "UsageFault", "RESERVED",
        "RESERVED", "RESERVED", "RESERVED", "SVCall",
@@ -52,7 +52,7 @@ static char *armv7m_exception_strings[] = {
 };
 
 /* PSP is used in some thread modes */
-const int armv7m_psp_reg_map[17] = {
+const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = {
        ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
        ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
        ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
@@ -61,7 +61,7 @@ const int armv7m_psp_reg_map[17] = {
 };
 
 /* MSP is used in handler and some thread modes */
-const int armv7m_msp_reg_map[17] = {
+const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
        ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
        ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
        ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
@@ -110,6 +110,25 @@ static const struct {
        { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
        { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
        { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+
+       { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+       { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+
+       { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" },
 };
 
 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
@@ -129,10 +148,10 @@ int armv7m_restore_context(struct target *target)
        if (armv7m->pre_restore_context)
                armv7m->pre_restore_context(target);
 
-       for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
+       for (i = cache->num_regs - 1; i >= 0; i--) {
                if (cache->reg_list[i].dirty) {
-                       uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32);
-                       armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value);
+                       armv7m->arm.write_core_reg(target, &cache->reg_list[i], i,
+                                                  ARM_MODE_ANY, cache->reg_list[i].value);
                }
        }
 
@@ -148,7 +167,7 @@ int armv7m_restore_context(struct target *target)
  * They are assigned by vendors, which generally assign different numbers to
  * peripherals (such as UART0 or a USB peripheral controller).
  */
-char *armv7m_exception_string(int number)
+const char *armv7m_exception_string(int number)
 {
        static char enamebuf[32];
 
@@ -179,12 +198,11 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
 {
        struct arm_reg *armv7m_reg = reg->arch_info;
        struct target *target = armv7m_reg->target;
-       uint32_t value = buf_get_u32(buf, 0, 32);
 
        if (target->state != TARGET_HALTED)
                return ERROR_TARGET_NOT_HALTED;
 
-       buf_set_u32(reg->value, 0, 32, value);
+       buf_cpy(buf, reg->value, reg->size);
        reg->dirty = 1;
        reg->valid = 1;
 
@@ -202,10 +220,28 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r,
        assert(num < (int)armv7m->arm.core_cache->num_regs);
 
        armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
-       retval = armv7m->load_core_reg_u32(target,
-                       armv7m_core_reg->num, &reg_value);
 
-       buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+       if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
+               /* map D0..D15 to S0..S31 */
+               size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
+               retval = armv7m->load_core_reg_u32(target, regidx, &reg_value);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf_set_u32(armv7m->arm.core_cache->reg_list[num].value,
+                           0, 32, reg_value);
+               retval = armv7m->load_core_reg_u32(target, regidx + 1, &reg_value);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4,
+                           0, 32, reg_value);
+       } else {
+               retval = armv7m->load_core_reg_u32(target,
+                                                  armv7m_core_reg->num, &reg_value);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+       }
+
        armv7m->arm.core_cache->reg_list[num].valid = 1;
        armv7m->arm.core_cache->reg_list[num].dirty = 0;
 
@@ -213,31 +249,47 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r,
 }
 
 static int armv7m_write_core_reg(struct target *target, struct reg *r,
-       int num, enum arm_mode mode, uint32_t value)
+       int num, enum arm_mode mode, uint8_t *value)
 {
        int retval;
-       uint32_t reg_value;
        struct arm_reg *armv7m_core_reg;
        struct armv7m_common *armv7m = target_to_armv7m(target);
 
        assert(num < (int)armv7m->arm.core_cache->num_regs);
 
-       reg_value = buf_get_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32);
        armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
-       retval = armv7m->store_core_reg_u32(target,
-                       armv7m_core_reg->num,
-                       reg_value);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("JTAG failure");
-               armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
-               return ERROR_JTAG_DEVICE_ERROR;
+
+       if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
+               /* map D0..D15 to S0..S31 */
+               size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
+
+               uint32_t t = buf_get_u32(value, 0, 32);
+               retval = armv7m->store_core_reg_u32(target, regidx, t);
+               if (retval != ERROR_OK)
+                       goto out_error;
+
+               t = buf_get_u32(value + 4, 0, 32);
+               retval = armv7m->store_core_reg_u32(target, regidx + 1, t);
+               if (retval != ERROR_OK)
+                       goto out_error;
+       } else {
+               uint32_t t = buf_get_u32(value, 0, 32);
+
+               LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t);
+               retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->num, t);
+               if (retval != ERROR_OK)
+                       goto out_error;
        }
 
-       LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
        armv7m->arm.core_cache->reg_list[num].valid = 1;
        armv7m->arm.core_cache->reg_list[num].dirty = 0;
 
        return ERROR_OK;
+
+out_error:
+       LOG_ERROR("Error setting register");
+       armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
+       return ERROR_JTAG_DEVICE_ERROR;
 }
 
 /**
@@ -250,9 +302,9 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
        int i;
 
        if (reg_class == REG_CLASS_ALL)
-               *reg_list_size = ARMV7M_NUM_REGS;
+               *reg_list_size = armv7m->arm.core_cache->num_regs;
        else
-               *reg_list_size = 17;
+               *reg_list_size = ARMV7M_NUM_CORE_REGS;
 
        *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
        if (*reg_list == NULL)
@@ -316,7 +368,7 @@ int armv7m_start_algorithm(struct target *target,
 
        /* refresh core register cache
         * Not needed if core register cache is always consistent with target process state */
-       for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) {
+       for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) {
 
                armv7m_algorithm_info->context[i] = buf_get_u32(
                                armv7m->arm.core_cache->reg_list[i].value,
@@ -451,7 +503,7 @@ int armv7m_wait_algorithm(struct target *target,
                }
        }
 
-       for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
+       for (int i = armv7m->arm.core_cache->num_regs - 1; i >= 0; i--) {
                uint32_t regvalue;
                regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
                if (regvalue != armv7m_algorithm_info->context[i]) {
@@ -535,7 +587,10 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
 
                reg_list[i].name = armv7m_regs[i].name;
                reg_list[i].size = armv7m_regs[i].bits;
-               reg_list[i].value = calloc(1, 4);
+               size_t storage_size = DIV_ROUND_UP(armv7m_regs[i].bits, 8);
+               if (storage_size < 4)
+                       storage_size = 4;
+               reg_list[i].value = calloc(1, storage_size);
                reg_list[i].dirty = 0;
                reg_list[i].valid = 0;
                reg_list[i].type = &armv7m_reg_type;
@@ -567,6 +622,34 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
        return cache;
 }
 
+void armv7m_free_reg_cache(struct target *target)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct arm *arm = &armv7m->arm;
+       struct reg_cache *cache;
+       struct reg *reg;
+       unsigned int i;
+
+       cache = arm->core_cache;
+
+       if (!cache)
+               return;
+
+       for (i = 0; i < cache->num_regs; i++) {
+               reg = &cache->reg_list[i];
+
+               free(reg->feature);
+               free(reg->reg_data_type);
+               free(reg->value);
+       }
+
+       free(cache->reg_list[0].arch_info);
+       free(cache->reg_list);
+       free(cache);
+
+       arm->core_cache = NULL;
+}
+
 static int armv7m_setup_semihosting(struct target *target, int enable)
 {
        /* nothing todo for armv7m */
@@ -580,6 +663,9 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 
        armv7m->common_magic = ARMV7M_COMMON_MAGIC;
        armv7m->fp_feature = FP_NONE;
+       armv7m->trace_config.trace_bus_id = 1;
+       /* Enable stimulus port #0 by default */
+       armv7m->trace_config.itm_ter[0] = 1;
 
        arm->core_type = ARM_MODE_THREAD;
        arm->arch_info = armv7m;
@@ -600,40 +686,8 @@ int armv7m_checksum_memory(struct target *target,
        struct reg_param reg_params[2];
        int retval;
 
-       /* see contrib/loaders/checksum/armv7m_crc.s for src */
-
        static const uint8_t cortex_m_crc_code[] = {
-               /* main: */
-               0x02, 0x46,                     /* mov          r2, r0 */
-               0x00, 0x20,                     /* movs         r0, #0 */
-               0xC0, 0x43,                     /* mvns         r0, r0 */
-               0x0A, 0x4E,                     /* ldr          r6, CRC32XOR */
-               0x0B, 0x46,                     /* mov          r3, r1 */
-               0x00, 0x24,                     /* movs         r4, #0 */
-               0x0D, 0xE0,                     /* b            ncomp */
-               /* nbyte: */
-               0x11, 0x5D,                     /* ldrb         r1, [r2, r4] */
-               0x09, 0x06,                     /* lsls         r1, r1, #24 */
-               0x48, 0x40,                     /* eors         r0, r0, r1 */
-               0x00, 0x25,                     /* movs         r5, #0 */
-               /* loop: */
-               0x00, 0x28,                     /* cmp          r0, #0 */
-               0x02, 0xDA,                     /* bge          notset */
-               0x40, 0x00,                     /* lsls         r0, r0, #1 */
-               0x70, 0x40,                     /* eors         r0, r0, r6 */
-               0x00, 0xE0,                     /* b            cont */
-               /* notset: */
-               0x40, 0x00,                     /* lsls         r0, r0, #1 */
-               /* cont: */
-               0x01, 0x35,                     /* adds         r5, r5, #1 */
-               0x08, 0x2D,                     /* cmp          r5, #8 */
-               0xF6, 0xD1,                     /* bne          loop */
-               0x01, 0x34,                     /* adds         r4, r4, #1 */
-               /* ncomp: */
-               0x9C, 0x42,                     /* cmp          r4, r3 */
-               0xEF, 0xD1,                     /* bne          nbyte */
-               0x00, 0xBE,                     /* bkpt         #0 */
-               0xB7, 0x1D, 0xC1, 0x04  /* CRC32XOR:    .word   0x04c11db7 */
+#include "../../contrib/loaders/checksum/armv7m_crc.inc"
        };
 
        retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
@@ -683,16 +737,8 @@ int armv7m_blank_check_memory(struct target *target,
        struct armv7m_algorithm armv7m_info;
        int retval;
 
-       /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */
-
        static const uint8_t erase_check_code[] = {
-               /* loop: */
-               0x03, 0x78,             /* ldrb r3, [r0] */
-               0x01, 0x30,             /* adds r0, #1 */
-               0x1A, 0x40,             /* ands r2, r2, r3 */
-               0x01, 0x39,             /* subs r1, r1, #1 */
-               0xFA, 0xD1,             /* bne  loop */
-               0x00, 0xBE              /* bkpt #0 */
+#include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
        };
 
        /* make sure we have a working area */
@@ -703,7 +749,7 @@ int armv7m_blank_check_memory(struct target *target,
        retval = target_write_buffer(target, erase_check_algorithm->address,
                        sizeof(erase_check_code), (uint8_t *)erase_check_code);
        if (retval != ERROR_OK)
-               return retval;
+               goto cleanup;
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
        armv7m_info.core_mode = ARM_MODE_THREAD;
@@ -734,6 +780,7 @@ int armv7m_blank_check_memory(struct target *target,
        destroy_reg_param(&reg_params[1]);
        destroy_reg_param(&reg_params[2]);
 
+cleanup:
        target_free_working_area(target, erase_check_algorithm);
 
        return retval;

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)