Some cleanup of the ARMv7-M support:

 - Reference the relevant ARMv7-M ARM doc (DDI 0405C to non-Vendors), and
   update the Cortex-M3 doc refs (DDI 0337C is no longer available).

 - Those registers aren't actually general, and some are incorrect (per all
   public docs anyway).  Update comments and code accordingly.

     * What the Core Debug facility exposes is *implementation-specific*
       not architectural.  These values aren't fully portable.  They match
       Cortex-M3 ... so no current implementation will make trouble, but
       the next v7m implementation might.

     * Four of the registers are actually not exposed that way.  Before
       Cortex-M3 r2p0 they are read/written through MRS/MSR instructions.
       In that newest silicon, they are four bytes in one register, not
       four separate registers.

 - Update the CM3 code to report when that one register is available,
   and not try to access it when it isn't.  Also declare the register
   numbers that an eventual MRS/MSR solution will need to be using.

 - Stop line wrapping the exception labels.

So for parts before r2p0 OpenOCD behavior is effectively unchanged, and
still buggy; but for those newer parts a few things might now be correct.

Most current Cortex-M3 parts use r1p1 (or earlier); this seems to include
most LM3S parts and all STM32 parts.  Parts using r2p0 are available, and
include fourth generation LM3S parts ("Tempest") plus AT91SAM3 and LPC17xx
parts which are now sampling.
---
The RFT is:  if you have an r2p0 part, can you verify that this will now
properly report "user thread" status (e.g. set breakpoint in non-privileged
thread).  Also, maybe Magnus can tell if this bit of logic was always-broken
or if it relied on some behavior that might have been experimental in early
silicon.

Sanity tested on an r1p1 part.

 src/target/armv7m.c    |   41 ++++++++++++++++++++++++++-------------
 src/target/armv7m.h    |   14 +++++++++----
 src/target/cortex_m3.c |   49 +++++++++++++++++++++++++++++------------------
 src/target/cortex_m3.h |   15 ++++++++++++++
 4 files changed, 84 insertions(+), 35 deletions(-)

Some cleanup of the ARMv7-M support:

 - Reference the relevant ARMv7-M ARM doc (DDI 0405C to non-Vendors), and
   update the Cortex-M3 doc refs (DDI 0337C is no longer available).

 - Those registers aren't actually general, and some are incorrect (per all
   public docs anyway).  Update comments and code accordingly.

     * What the Core Debug facility exposes is *implementation-specific*
       not architectural.  These values aren't fully portable.  They match
       Cortex-M3 ... so no current implementation will make trouble, but
       the next v7m implementation might.

     * Four of the registers are actually not exposed that way.  Before
       Cortex-M3 r2p0 they are read/written through MRS/MSR instructions.
       In that newest silicon, they are four bytes in one register, not
       four separate registers.

 - Update the CM3 code to report when that one register is available,
   and not try to access it when it isn't.  Also declare the register
   numbers that an eventual MRS/MSR solution will need to be using.

 - Stop line wrapping the exception labels.

So for parts before r2p0 OpenOCD behavior is effectively unchanged, and
still buggy; but for those newer parts a few things might now be correct.

Most current Cortex-M3 parts use r1p1 (or earlier); this seems to include
most LM3S parts and all STM32 parts.  Parts using r2p0 are available, and
include fourth generation LM3S parts ("Tempest") plus AT91SAM3 and LPC17xx
parts which are now sampling.
---
 src/target/armv7m.c    |   41 ++++++++++++++++++++++++++-------------
 src/target/armv7m.h    |   14 +++++++++----
 src/target/cortex_m3.c |   49 +++++++++++++++++++++++++++++------------------
 src/target/cortex_m3.h |   15 ++++++++++++++
 4 files changed, 84 insertions(+), 35 deletions(-)

--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -25,6 +25,10 @@
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                         *
+ *	ARMv7-M Architecture, Application Level Reference Manual           *
+ *              ARM DDI 0405C (September 2008)                             *
+ *                                                                         *
  ***************************************************************************/
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -44,8 +48,10 @@ char* armv7m_mode_strings[] =
 
 char* armv7m_exception_strings[] =
 {
-	"", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
-	"SVCall", "DebugMonitor", "RESERVED", "PendSV", "SysTick"
+	"", "Reset", "NMI", "HardFault",
+	"MemManage", "BusFault", "UsageFault", "RESERVED",
+	"RESERVED", "RESERVED", "RESERVED", "SVCall",
+	"DebugMonitor", "RESERVED", "PendSV", "SysTick"
 };
 
 char* armv7m_core_reg_list[] =
@@ -54,8 +60,8 @@ char* armv7m_core_reg_list[] =
 	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
 	"sp", "lr", "pc",
 	"xPSR", "msp", "psp",
-	/* Registers accessed through special reg 20 */
-	"primask", "basepri", "faultmask", "control"
+	/* reg 20 has 4 bytes: CONTROL, FAULTMASK, BASEPRI, PRIMASK */
+	"spec20",
 };
 
 uint8_t armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -105,11 +111,11 @@ armv7m_core_reg_t armv7m_core_reg_list_a
 	{17, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* MSP */
 	{18, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* PSP */
 
-	/*  CORE_SP are accesible using coreregister 20 */
-	{19, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
-	{20, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* BASEPRI */
-	{21, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* FAULTMASK */
-	{22, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}  /* CONTROL */
+	/* FIXME the register numbers here are core-specific.
+	 * Numbers 0..18 above work for all Cortex-M3 revisions.
+	 * Number 20 below works for CM3 r2p0 and later.
+	 */
+	{20, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL},
 };
 
 int armv7m_core_reg_arch_type = -1;
@@ -381,12 +387,21 @@ int armv7m_run_algorithm(struct target_s
 		armv7m_set_core_reg(reg, reg_params[i].value);
 	}
 
-	if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
+	/* NOTE:  CONTROL is bits 31:24 of SPEC20 register, if it's present;
+	 * holding a two-bit field.
+	 *
+	 * FIXME need a solution using ARMV7M_T_MSR().  Use it at least for
+	 * earlier cores.
+	 */
+	if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY
+			&& armv7m->has_spec20)
 	{
 		LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
-		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode);
-		armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
-		armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
+
+		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_SPEC20].value,
+				24, 2, armv7m_algorithm_info->core_mode);
+		armv7m->core_cache->reg_list[ARMV7M_SPEC20].dirty = 1;
+		armv7m->core_cache->reg_list[ARMV7M_SPEC20].valid = 1;
 	}
 
 	/* ARMV7M always runs in Thumb state */
--- a/src/target/armv7m.h
+++ b/src/target/armv7m.h
@@ -61,10 +61,15 @@ enum
 	ARMV7M_xPSR = 16,
 	ARMV7M_MSP,
 	ARMV7M_PSP,
-	ARMV7M_PRIMASK,
-	ARMV7M_BASEPRI,
-	ARMV7M_FAULTMASK,
-	ARMV7M_CONTROL,
+
+	/* FIXME the register numbers here are core-specific.  Cortex-M3
+	 * through r1p1 only defines registers up to PSP; see ARM DDI 0337E.
+	 *
+	 * It's r2p0 (see ARM DDI 0337G) which defines the register that's
+	 * called SPEC20 here, with four single-byte fields with CONTROL
+	 * (highest byte), FAULTMASK, BASEPRI, and PRIMASK (lowest byte).
+	 */
+	ARMV7M_SPEC20 = 20,
 	ARMV7NUMCOREREGS
 };
 
@@ -78,6 +83,7 @@ typedef struct armv7m_common_s
 	int exception_number;
 	swjdp_common_t swjdp_info;
 
+	bool has_spec20;
 
 	/* Direct processor core register read and writes */
 	int (*load_core_reg_u32)(struct target_s *target, enum armv7m_regtype type, uint32_t num, uint32_t *value);
--- a/src/target/cortex_m3.c
+++ b/src/target/cortex_m3.c
@@ -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
@@ -394,7 +394,7 @@ int cortex_m3_debug_entry(target_t *targ
 
 	/* 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 +417,19 @@ int cortex_m3_debug_entry(target_t *targ
 		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 +632,26 @@ int cortex_m3_resume(struct target_s *ta
 	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 +1473,14 @@ int cortex_m3_examine(struct target_s *t
 		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);
--- a/src/target/cortex_m3.h
+++ b/src/target/cortex_m3.h
@@ -117,6 +117,21 @@ extern char* cortex_m3_state_strings[];
 #define FPCR_REPLACE_BKPT_HIGH  (2 << 30)
 #define FPCR_REPLACE_BKPT_BOTH  (3 << 30)
 
+/* Use MRS/MSR to read/write any of these special registers.  Some of
+ * them (xPSR, MSP, PSP) are always available using DCRxR.  Starting in
+ * Cortex-M3 r2p0, some (CONTROL, BASEPRI, and *MASK) are also available
+ * through DCRxR.
+ * NOTE: this listing omits xPSR components and other mixtures.
+ */
+#define SR_XPSR		3
+#define SR_MSP		8
+#define SR_PSP		9
+#define SR_PRIMASK	16
+#define SR_BASEPRI	17
+#define SR_BASEPRI_MAX	18
+#define SR_FAULTMASK	19
+#define SR_CONTROL	20
+
 typedef struct  cortex_m3_fp_comparator_s
 {
 	int used;
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to