target/armv7m,cortex_m: introduce checked arch_info cast routines
[fw/openocd] / src / target / cortex_m.h
index 415a6c22f301d001403c92c0f765e04fb42783ac..8fb34f46c12fa2ce49b4aeb4cf98c370f8a2461d 100644 (file)
 #define ITM_TER0       0xE0000E00
 #define ITM_TPR                0xE0000E40
 #define ITM_TCR                0xE0000E80
+#define ITM_TCR_ITMENA_BIT     BIT(0)
+#define ITM_TCR_BUSY_BIT       BIT(23)
 #define ITM_LAR                0xE0000FB0
 #define ITM_LAR_KEY    0xC5ACCE55
 
 #define CPUID          0xE000ED00
 
-#define ARM_CPUID_PARTNO_MASK  0xFFF0
+#define ARM_CPUID_PARTNO_POS    4
+#define ARM_CPUID_PARTNO_MASK  (0xFFF << ARM_CPUID_PARTNO_POS)
+
+enum cortex_m_partno {
+       CORTEX_M0_PARTNO   = 0xC20,
+       CORTEX_M1_PARTNO   = 0xC21,
+       CORTEX_M3_PARTNO   = 0xC23,
+       CORTEX_M4_PARTNO   = 0xC24,
+       CORTEX_M7_PARTNO   = 0xC27,
+       CORTEX_M0P_PARTNO  = 0xC60,
+       CORTEX_M23_PARTNO  = 0xD20,
+       CORTEX_M33_PARTNO  = 0xD21,
+       CORTEX_M35P_PARTNO = 0xD31,
+       CORTEX_M55_PARTNO  = 0xD22,
+};
+
+/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
+#define CORTEX_M_F_HAS_FPV4               BIT(0)
+#define CORTEX_M_F_HAS_FPV5               BIT(1)
+#define CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K  BIT(2)
 
-#define CORTEX_M23_PARTNO      0xD200
-#define CORTEX_M33_PARTNO      0xD210
-#define CORTEX_M35P_PARTNO     0xD310
-#define CORTEX_M55_PARTNO      0xD220
+struct cortex_m_part_info {
+       enum cortex_m_partno partno;
+       const char *name;
+       enum arm_arch arch;
+       uint32_t flags;
+};
 
 /* Debug Control Block */
 #define DCB_DHCSR      0xE000EDF0
@@ -54,7 +77,7 @@
 #define DCB_DEMCR      0xE000EDFC
 #define DCB_DSCSR      0xE000EE08
 
-#define DCRSR_WnR      BIT(16)
+#define DCRSR_WNR      BIT(16)
 
 #define DWT_CTRL       0xE0001000
 #define DWT_CYCCNT     0xE0001004
 #define NVIC_AIRCR             0xE000ED0C
 #define NVIC_SHCSR             0xE000ED24
 #define NVIC_CFSR              0xE000ED28
-#define NVIC_MMFSRb            0xE000ED28
-#define NVIC_BFSRb             0xE000ED29
-#define NVIC_USFSRh            0xE000ED2A
+#define NVIC_MMFSRB            0xE000ED28
+#define NVIC_BFSRB             0xE000ED29
+#define NVIC_USFSRH            0xE000ED2A
 #define NVIC_HFSR              0xE000ED2C
 #define NVIC_DFSR              0xE000ED30
 #define NVIC_MMFAR             0xE000ED34
@@ -190,30 +213,33 @@ struct cortex_m_common {
 
        /* Context information */
        uint32_t dcb_dhcsr;
+       uint32_t dcb_dhcsr_cumulated_sticky;
        uint32_t nvic_dfsr;  /* Debug Fault Status Register - shows reason for debug halt */
        uint32_t nvic_icsr;  /* Interrupt Control State Register - shows active and pending IRQ */
 
        /* Flash Patch and Breakpoint (FPB) */
-       int fp_num_lit;
-       int fp_num_code;
+       unsigned int fp_num_lit;
+       unsigned int fp_num_code;
        int fp_rev;
        bool fpb_enabled;
        struct cortex_m_fp_comparator *fp_comparator_list;
 
        /* Data Watchpoint and Trace (DWT) */
-       int dwt_num_comp;
-       int dwt_comp_available;
+       unsigned int dwt_num_comp;
+       unsigned int dwt_comp_available;
        uint32_t dwt_devarch;
        struct cortex_m_dwt_comparator *dwt_comparator_list;
        struct reg_cache *dwt_cache;
 
        enum cortex_m_soft_reset_config soft_reset_config;
        bool vectreset_supported;
-
        enum cortex_m_isrmasking_mode isrmasking_mode;
 
+       const struct cortex_m_part_info *core_info;
        struct armv7m_common armv7m;
 
+       bool slow_register_read;        /* A register has not been ready, poll S_REGRDY */
+
        int apsel;
 
        /* Whether this target has the erratum that makes C_MASKINTS not apply to
@@ -221,11 +247,51 @@ struct cortex_m_common {
        bool maskints_erratum;
 };
 
+static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
+{
+       return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC;
+}
+
+static inline bool is_cortex_m_with_dap_access(const struct cortex_m_common *cortex_m)
+{
+       if (!is_cortex_m_or_hla(cortex_m))
+               return false;
+
+       return !cortex_m->armv7m.is_hla_target;
+}
+
+/**
+ * @returns the pointer to the target specific struct
+ * without matching a magic number.
+ * Use in target specific service routines, where the correct
+ * type of arch_info is certain.
+ */
 static inline struct cortex_m_common *
 target_to_cm(struct target *target)
 {
        return container_of(target->arch_info,
-                       struct cortex_m_common, armv7m);
+                       struct cortex_m_common, armv7m.arm);
+}
+
+/**
+ * @returns the pointer to the target specific struct
+ * or NULL if the magic number does not match.
+ * Use in a flash driver or any place where mismatch of the arch_info
+ * type can happen.
+ */
+static inline struct cortex_m_common *
+target_to_cortex_m_safe(struct target *target)
+{
+       /* Check the parent types first to prevent peeking memory too far
+        * from arch_info pointer */
+       if (!target_to_armv7m_safe(target))
+               return NULL;
+
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       if (!is_cortex_m_or_hla(cortex_m))
+               return NULL;
+
+       return cortex_m;
 }
 
 int cortex_m_examine(struct target *target);
@@ -233,13 +299,10 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
 int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);
 int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
 int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint);
-int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint);
 int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint);
 int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint);
 void cortex_m_enable_breakpoints(struct target *target);
 void cortex_m_enable_watchpoints(struct target *target);
-void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target);
 void cortex_m_deinit_target(struct target *target);
 int cortex_m_profiling(struct target *target, uint32_t *samples,
        uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);