+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
/***************************************************************************
* Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_TARGET_CORTEX_M_H
#include "armv7m.h"
#include "helper/bits.h"
-#define CORTEX_M_COMMON_MAGIC 0x1A451A45
+#define CORTEX_M_COMMON_MAGIC 0x1A451A45U
#define SYSTEM_CONTROL_BASE 0x400FE000
#define CPUID 0xE000ED00
-#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,
+#define ARM_CPUID_IMPLEMENTOR_POS 24
+#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS)
+#define ARM_CPUID_PARTNO_POS 4
+#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
+
+#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \
+ (((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK))
+
+/** Known Arm Cortex masked CPU Ids
+ * This includes the implementor and part number, but _not_ the revision or
+ * patch fields.
+ */
+enum cortex_m_impl_part {
+ CORTEX_M_PARTNO_INVALID,
+ STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
+ CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
+ CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
+ CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
+ CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
+ CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
+ CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
+ CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
+ CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
+ CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
+ CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
+ REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
+ REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
};
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
#define CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K BIT(2)
struct cortex_m_part_info {
- enum cortex_m_partno partno;
+ enum cortex_m_impl_part impl_part;
const char *name;
enum arm_arch arch;
uint32_t flags;
#define DCB_DEMCR 0xE000EDFC
#define DCB_DSCSR 0xE000EE08
+#define DAUTHSTATUS 0xE000EFB8
+#define DAUTHSTATUS_SID_MASK 0x00000030
+
#define DCRSR_WNR BIT(16)
#define DWT_CTRL 0xE0001000
};
struct cortex_m_common {
- int common_magic;
+ unsigned int common_magic;
+
+ struct armv7m_common armv7m;
/* Context information */
uint32_t dcb_dhcsr;
+ uint32_t dcb_dhcsr_cumulated_sticky;
+ /* DCB DHCSR has been at least once read, so the sticky bits have been reset */
+ bool dcb_dhcsr_sticky_is_recent;
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 */
enum cortex_m_isrmasking_mode isrmasking_mode;
const struct cortex_m_part_info *core_info;
- struct armv7m_common armv7m;
- int apsel;
+ bool slow_register_read; /* A register has not been ready, poll S_REGRDY */
+
+ uint64_t apsel;
/* Whether this target has the erratum that makes C_MASKINTS not apply to
* already pending interrupts */
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;
+}
+
+/**
+ * @returns cached value of the cpuid, masked for implementation and part.
+ * or CORTEX_M_PARTNO_INVALID if the magic number does not match
+ * or core_info is not initialised.
+ */
+static inline enum cortex_m_impl_part cortex_m_get_impl_part(struct target *target)
+{
+ struct cortex_m_common *cortex_m = target_to_cortex_m_safe(target);
+ if (!cortex_m)
+ return CORTEX_M_PARTNO_INVALID;
+
+ if (!cortex_m->core_info)
+ return CORTEX_M_PARTNO_INVALID;
+
+ return cortex_m->core_info->impl_part;
}
int cortex_m_examine(struct target *target);