Magnus Lundin <lundin@mlu.mine.nu>, Oyvind Harboe <oyvind.harboe@zylin.com>, David...
[openocd.git] / src / target / cortex_m3.c
index 53ecd0a90d5309e89de466efed373f37a438308a..8cb1bd4e7a69c5dd09527500cc48e4fcb44436fe 100644 (file)
@@ -24,7 +24,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  *                                                                         *
  *                                                                         *
- *   Cortex-M3(tm) TRM, ARM DDI 0337C                                      *
+ *   Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0)              *
  *                                                                         *
  ***************************************************************************/
 #ifdef HAVE_CONFIG_H
@@ -34,6 +34,7 @@
 #include "cortex_m3.h"
 #include "target_request.h"
 #include "target_type.h"
+#include "arm_disassembler.h"
 
 
 /* cli handling */
@@ -394,7 +395,7 @@ int cortex_m3_debug_entry(target_t *target)
 
        /* Examine target state and mode */
        /* First load register acessible through core debug port*/
-       for (i = 0; i < ARMV7M_PRIMASK; i++)
+       for (i = 0; i < ARMV7NUMCOREREGS; i++)
        {
                if (!armv7m->core_cache->reg_list[i].valid)
                        armv7m->read_core_reg(target, i);
@@ -417,22 +418,19 @@ int cortex_m3_debug_entry(target_t *target)
                cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
        }
 
-       /* Now we can load SP core registers */
-       for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
-       {
-               if (!armv7m->core_cache->reg_list[i].valid)
-                       armv7m->read_core_reg(target, i);
-       }
-
        /* Are we in an exception handler */
        if (xPSR & 0x1FF)
        {
                armv7m->core_mode = ARMV7M_MODE_HANDLER;
                armv7m->exception_number = (xPSR & 0x1FF);
        }
-       else
+       else if (armv7m->has_spec20)
        {
-               armv7m->core_mode = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1);
+               /* NOTE:  CONTROL is bits 31:24 of SPEC20 register, holding
+                * a two-bit field.  Unavailable before r2p0...
+                */
+               armv7m->core_mode = buf_get_u32(
+                       armv7m->core_cache->reg_list[ARMV7M_SPEC20].value, 24, 2);
                armv7m->exception_number = 0;
        }
 
@@ -635,16 +633,26 @@ int cortex_m3_resume(struct target_s *target, int current, uint32_t address, int
        if (debug_execution)
        {
                /* Disable interrupts */
-               /* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
+               /* We disable interrupts in the PRIMASK register instead
+                * of masking with C_MASKINTS,
                 * This is probably the same issue as Cortex-M3 Errata  377493:
-                * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */
-               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
+                * C_MASKINTS in parallel with disabled interrupts can cause
+                * local faults to not be taken.  (FIXED in r1p0 and later.)
+                *
+                * NOTE:  PRIMASK is bits 7:0 of SPEC20 register, holding a
+                * one bit field.  Available this way for r2p0 and later...
+                */
+               if (armv7m->has_spec20) {
+                       buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_SPEC20]
+                                       .value, 0, 1, 1);
+                       armv7m->core_cache->reg_list[ARMV7M_SPEC20].dirty = 1;
+                       armv7m->core_cache->reg_list[ARMV7M_SPEC20].valid = 1;
+               }
 
                /* Make sure we are in Thumb mode */
                buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
-                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
+                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32)
+                       | (1 << 24));
                armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
                armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
        }
@@ -1466,8 +1474,14 @@ int cortex_m3_examine(struct target_s *target)
                if ((retval = target_read_u32(target, CPUID, &cpuid)) != ERROR_OK)
                        return retval;
 
-               if (((cpuid >> 4) & 0xc3f) == 0xc23)
+               if (((cpuid >> 4) & 0xc3f) == 0xc23) {
                        LOG_DEBUG("CORTEX-M3 processor detected");
+                       if (((cpuid >> 20) & 0xf) >= 2) {
+                               armv7m->has_spec20 = true;
+                               LOG_DEBUG("r2p0 or later detected");
+                       }
+               } else
+                       LOG_WARNING("not a CORTEX-M3 processor?");
                LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
 
                target_read_u32(target, NVIC_ICTR, &ictr);
@@ -1646,6 +1660,47 @@ int cortex_m3_target_create(struct target_s *target, Jim_Interp *interp)
        return ERROR_OK;
 }
 
+/*
+ * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
+ * as at least ARM-1156T2.  The interesting thing about Cortex-M is
+ * that *only* Thumb2 disassembly matters.  There are also some small
+ * additions to Thumb2 that are specific to ARMv7-M.
+ */
+static int
+handle_cortex_m3_disassemble_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
+       int retval = ERROR_OK;
+       target_t *target = get_current_target(cmd_ctx);
+       uint32_t address;
+       unsigned long count;
+       arm_instruction_t cur_instruction;
+
+       if (argc != 2) {
+               command_print(cmd_ctx,
+                       "usage: cortex_m3 disassemble <address> <count>");
+               return ERROR_OK;
+       }
+
+       errno = 0;
+       address = strtoul(args[0], NULL, 0);
+       if (errno)
+               return ERROR_FAIL;
+       count = strtoul(args[1], NULL, 0);
+       if (errno)
+               return ERROR_FAIL;
+
+       while (count--) {
+               retval = thumb2_opcode(target, address, &cur_instruction);
+               if (retval != ERROR_OK)
+                       return retval;
+               command_print(cmd_ctx, "%s", cur_instruction.text);
+               address += cur_instruction.instruction_size;
+       }
+
+       return ERROR_OK;
+}
+
 int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
 {
        int retval;
@@ -1653,8 +1708,15 @@ int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
 
        retval = armv7m_register_commands(cmd_ctx);
 
-       cortex_m3_cmd = register_command(cmd_ctx, NULL, "cortex_m3", NULL, COMMAND_ANY, "cortex_m3 specific commands");
-       register_command(cmd_ctx, cortex_m3_cmd, "maskisr", handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC, "mask cortex_m3 interrupts ['on'|'off']");
+       cortex_m3_cmd = register_command(cmd_ctx, NULL, "cortex_m3",
+                       NULL, COMMAND_ANY, "cortex_m3 specific commands");
+
+       register_command(cmd_ctx, cortex_m3_cmd, "disassemble",
+                       handle_cortex_m3_disassemble_command, COMMAND_EXEC,
+                       "disassemble Thumb2 instructions <address> <count>");
+       register_command(cmd_ctx, cortex_m3_cmd, "maskisr",
+                       handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC,
+                       "mask cortex_m3 interrupts ['on'|'off']");
 
        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)