ARMv7-M: start using "struct arm"
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 21 Feb 2010 22:28:53 +0000 (14:28 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 21 Feb 2010 22:28:53 +0000 (14:28 -0800)
This sets up a few of the core "struct arm" data structures so they
can be used with ARMv7-M cores.  Specifically, it:

 - defines new ARM core_modes to match the microcontroller modes
   (e.g. HANDLER not IRQ, and two types of thread mode);

 - Establishes a new microcontroller "core_type", which can be
   used to make sure v7-M (and v6-M) cores are handled right;

 - adds "struct arm" to "struct armv7m" and arranges for the
   target_to_armv7m() converter to use it;

 - sets up the arm.core_cache and arm.cpsr values

 - makes the Cortex-M3 code maintain arm.map and arm.core_mode.

This is currently set up as a parallel data structure, primarily to
minimize special cases for the semihosting support with microcontroller
profile cores.

Later patches can rip out the duplicative ARMv7-M support and start
reusing core ARM code.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm.h
src/target/armv4_5.c
src/target/armv7m.c
src/target/armv7m.h
src/target/cortex_m3.c

index 988266e3cf9bdb6fa164325d8dc3f653b7a318c8..c72b194267b0a8f12ddc3b9086b17d89288ed2bb 100644 (file)
  */
 
 /**
- * These numbers match the five low bits of the *PSR registers on
+ * Represent state of an ARM core.
+ *
+ * Most numbers match the five low bits of the *PSR registers on
  * "classic ARM" processors, which build on the ARMv4 processor
  * modes and register set.
+ *
+ * ARM_MODE_ANY is a magic value, often used as a wildcard.
+ *
+ * Only the microcontroller cores (ARMv6-M, ARMv7-M) support ARM_MODE_THREAD,
+ * ARM_MODE_USER_THREAD, and ARM_MODE_HANDLER.  Those are the only modes
+ * they support.
  */
 enum arm_mode {
        ARM_MODE_USR = 16,
@@ -53,6 +61,11 @@ enum arm_mode {
        ARM_MODE_MON = 26,
        ARM_MODE_UND = 27,
        ARM_MODE_SYS = 31,
+
+       ARM_MODE_THREAD,
+       ARM_MODE_USER_THREAD,
+       ARM_MODE_HANDLER,
+
        ARM_MODE_ANY = -1
 };
 
@@ -96,6 +109,8 @@ struct arm {
         * ARM_MODE_ANY indicates the standard set of 37 registers,
         * seen on for example ARM7TDMI cores.  ARM_MODE_MON indicates three
         * more registers are shadowed, for "Secure Monitor" mode.
+        * ARM_MODE_THREAD indicates a microcontroller profile core,
+        * which only shadows SP.
         */
        enum arm_mode core_type;
 
index c7b73676aff7ce906839d66508b86c7bb7004d9c..8d3a8917d11581cfaa2399ae42c5086237176c02 100644 (file)
@@ -1426,10 +1426,12 @@ int arm_init_arch_info(struct target *target, struct arm *armv4_5)
        armv4_5->target = target;
 
        armv4_5->common_magic = ARM_COMMON_MAGIC;
-       arm_set_cpsr(armv4_5, ARM_MODE_USR);
 
        /* core_type may be overridden by subtype logic */
-       armv4_5->core_type = ARM_MODE_ANY;
+       if (armv4_5->core_type != ARM_MODE_THREAD) {
+               armv4_5->core_type = ARM_MODE_ANY;
+               arm_set_cpsr(armv4_5, ARM_MODE_USR);
+       }
 
        /* default full_context() has no core-specific optimizations */
        if (!armv4_5->full_context && armv4_5->read_core_reg)
index 9fe705af7c92c600e5a1a7deda61fe912cd14466..faa886b41a645f3fd8905b695c9048852d668c12 100644 (file)
@@ -473,6 +473,7 @@ int armv7m_run_algorithm(struct target *target,
 int armv7m_arch_state(struct target *target)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct arm *arm = &armv7m->arm;
        uint32_t ctrl, sp;
 
        ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
@@ -483,7 +484,7 @@ int armv7m_arch_state(struct target *target)
                debug_reason_name(target),
                armv7m_mode_strings[armv7m->core_mode],
                armv7m_exception_string(armv7m->exception_number),
-               buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
+               buf_get_u32(arm->cpsr->value, 0, 32),
                buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32),
                (ctrl & 0x02) ? 'p' : 'm',
                sp);
@@ -499,6 +500,7 @@ static const struct reg_arch_type armv7m_reg_type = {
 struct reg_cache *armv7m_build_reg_cache(struct target *target)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct arm *arm = &armv7m->arm;
        int num_regs = ARMV7M_NUM_REGS;
        struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
@@ -532,19 +534,28 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
                reg_list[i].arch_info = &arch_info[i];
        }
 
+       arm->cpsr = reg_list + ARMV7M_xPSR;
+       arm->core_cache = cache;
        return cache;
 }
 
 /** Sets up target as a generic ARMv7-M core */
 int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 {
+       struct arm *arm = &armv7m->arm;
+
        armv7m->common_magic = ARMV7M_COMMON_MAGIC;
 
-       target->arch_info = armv7m;
+       arm->core_type = ARM_MODE_THREAD;
+       arm->arch_info = armv7m;
+
+       /* FIXME remove v7m-specific r/w core_reg functions;
+        * use the generic ARM core support..
+        */
        armv7m->read_core_reg = armv7m_read_core_reg;
        armv7m->write_core_reg = armv7m_write_core_reg;
 
-       return ERROR_OK;
+       return arm_init_arch_info(target, arm);
 }
 
 /** Generates a CRC32 checksum of a memory region. */
index b6be1d22497e340ed542463a0df4e0b9efca4708..89c5064ccc934354c0dd29c7bb1b46aaad43ad59 100644 (file)
@@ -100,6 +100,8 @@ enum
 
 struct armv7m_common
 {
+       struct arm      arm;
+
        int common_magic;
        struct reg_cache *core_cache;
        enum armv7m_mode core_mode;
@@ -128,7 +130,7 @@ struct armv7m_common
 static inline struct armv7m_common *
 target_to_armv7m(struct target *target)
 {
-       return target->arch_info;
+       return container_of(target->arch_info, struct armv7m_common, arm);
 }
 
 static inline bool is_armv7m(struct armv7m_common *armv7m)
index 3f347697bd41a8ca76836f3e446225f5daa11fbd..fbc879f1b9a2339f69ccf3c684b14a8d9460c4c3 100644 (file)
@@ -323,6 +323,24 @@ static int cortex_m3_examine_exception_reason(struct target *target)
        return ERROR_OK;
 }
 
+/* PSP is used in some thread modes */
+static const int armv7m_psp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
+};
+
+/* MSP is used in handler and some thread modes */
+static const int armv7m_msp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
+};
+
 static int cortex_m3_debug_entry(struct target *target)
 {
        int i;
@@ -330,6 +348,7 @@ static int cortex_m3_debug_entry(struct target *target)
        int retval;
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
        struct armv7m_common *armv7m = &cortex_m3->armv7m;
+       struct arm *arm = &armv7m->arm;
        struct swjdp_common *swjdp = &armv7m->swjdp_info;
        struct reg *r;
 
@@ -377,11 +396,27 @@ static int cortex_m3_debug_entry(struct target *target)
        {
                armv7m->core_mode = ARMV7M_MODE_HANDLER;
                armv7m->exception_number = (xPSR & 0x1FF);
+
+               arm->core_mode = ARM_MODE_HANDLER;
+               arm->map = armv7m_msp_reg_map;
        }
        else
        {
-               armv7m->core_mode = buf_get_u32(armv7m->core_cache
-                               ->reg_list[ARMV7M_CONTROL].value, 0, 1);
+               unsigned control = buf_get_u32(armv7m->core_cache
+                               ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+
+               /* is this thread privileged? */
+               armv7m->core_mode = control & 1;
+               arm->core_mode = armv7m->core_mode
+                               ? ARM_MODE_USER_THREAD
+                               : ARM_MODE_THREAD;
+
+               /* which stack is it using? */
+               if (control & 2)
+                       arm->map = armv7m_psp_reg_map;
+               else
+                       arm->map = armv7m_msp_reg_map;
+
                armv7m->exception_number = 0;
        }
 

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)