You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2022/05/13 15:55:37 UTC

[incubator-nuttx] branch master updated (f095bf8f39 -> 701e56d4ae)

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


    from f095bf8f39 arch/arm/samv7/sam_afec: fix ADC pin for channel 9
     new 34b124bc14 arm/cortex-r: add _pmu_* perfix for performance monitor functions
     new 920e826a80 arm/cortex-r: rename PCMR_* to PMCR_*
     new 4da48c84ff arm/cortex-[a|r]: add more functions of Performance Monitors Unit
     new 701e56d4ae arm/cortex-[a|r]: add performance counter implement

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/armv7-a/Make.defs               |   1 +
 arch/arm/src/{armv8-m => armv7-a}/arm_perf.c |  41 ++-
 arch/arm/src/armv7-a/sctlr.h                 | 485 +++++++++++++++++++++++++++
 arch/arm/src/armv7-r/Make.defs               |   1 +
 arch/arm/src/{armv8-m => armv7-r}/arm_perf.c |  41 ++-
 arch/arm/src/armv7-r/sctlr.h                 | 423 +++++++++++++++++++++--
 arch/arm/src/tms570/tms570_boot.c            |   4 +-
 7 files changed, 938 insertions(+), 58 deletions(-)
 copy arch/arm/src/{armv8-m => armv7-a}/arm_perf.c (66%)
 copy arch/arm/src/{armv8-m => armv7-r}/arm_perf.c (66%)


[incubator-nuttx] 01/04: arm/cortex-r: add _pmu_* perfix for performance monitor functions

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 34b124bc14e6ab60946296fdc51b15265c5ce43d
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri May 13 17:03:14 2022 +0800

    arm/cortex-r: add _pmu_* perfix for performance monitor functions
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/arm/src/armv7-r/sctlr.h      | 4 ++--
 arch/arm/src/tms570/tms570_boot.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/src/armv7-r/sctlr.h b/arch/arm/src/armv7-r/sctlr.h
index 98db4980af..bdc2b77c12 100644
--- a/arch/arm/src/armv7-r/sctlr.h
+++ b/arch/arm/src/armv7-r/sctlr.h
@@ -526,7 +526,7 @@ static inline void cp15_wractlr(unsigned int actlr)
 
 /* Read/write the Performance Monitor Control Register (PMCR) */
 
-static inline unsigned int cp15_rdpmcr(void)
+static inline unsigned int cp15_pmu_rdpmcr(void)
 {
   unsigned int pmcr;
   __asm__ __volatile__
@@ -540,7 +540,7 @@ static inline unsigned int cp15_rdpmcr(void)
   return pmcr;
 }
 
-static inline void cp15_wrpmcr(unsigned int pmcr)
+static inline void cp15_pmu_wrpmcr(unsigned int pmcr)
 {
   __asm__ __volatile__
     (
diff --git a/arch/arm/src/tms570/tms570_boot.c b/arch/arm/src/tms570/tms570_boot.c
index dfdadd8dd7..363a3a6c5d 100644
--- a/arch/arm/src/tms570/tms570_boot.c
+++ b/arch/arm/src/tms570/tms570_boot.c
@@ -104,9 +104,9 @@
 
 static inline void tms570_event_export(void)
 {
-  uint32_t pmcr = cp15_rdpmcr();
+  uint32_t pmcr = cp15_pmu_rdpmcr();
   pmcr |= PCMR_X;
-  cp15_wrpmcr(pmcr);
+  cp15_pmu_wrpmcr(pmcr);
 }
 
 /****************************************************************************


[incubator-nuttx] 02/04: arm/cortex-r: rename PCMR_* to PMCR_*

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 920e826a8000498af98378a7f7f533972970db33
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri May 13 17:06:15 2022 +0800

    arm/cortex-r: rename PCMR_* to PMCR_*
    
    It should be PMCR (Performance Monitors Control Register)
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/arm/src/armv7-r/sctlr.h      | 24 ++++++++++++------------
 arch/arm/src/tms570/tms570_boot.c |  2 +-
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm/src/armv7-r/sctlr.h b/arch/arm/src/armv7-r/sctlr.h
index bdc2b77c12..8974ce1c45 100644
--- a/arch/arm/src/armv7-r/sctlr.h
+++ b/arch/arm/src/armv7-r/sctlr.h
@@ -251,18 +251,18 @@
  * TODO: To be provided
  */
 
-#define PCMR_E             (1 << 0)  /* Enable all counters */
-#define PCMR_P             (1 << 1)  /* Reset all counter eventts (except PMCCNTR) */
-#define PCMR_C             (1 << 2)  /* Reset cycle counter (PMCCNTR) to zero */
-#define PCMR_D             (1 << 3)  /* Enable cycle counter clock (PMCCNTR) divider */
-#define PCMR_X             (1 << 4)  /* Export of events is enabled */
-#define PCMR_DP            (1 << 5)  /* Disable PMCCNTR if event counting is prohibited */
-#define PCMR_N_SHIFT       (11)      /* Bits 11-15:  Number of event counters */
-#define PCMR_N_MASK        (0x1f << PCMR_N_SHIFT)
-#define PCMR_IDCODE_SHIFT  (16)      /* Bits 16-23: Identification code */
-#define PCMR_IDCODE_MASK   (0xff << PCMR_IDCODE_SHIFT)
-#define PCMR_IMP_SHIFT     (24)      /* Bits 24-31: Implementer code */
-#define PCMR_IMP_MASK      (0xff << PCMR_IMP_SHIFT)
+#define PMCR_E             (1 << 0)  /* Enable all counters */
+#define PMCR_P             (1 << 1)  /* Reset all counter eventts (except PMCCNTR) */
+#define PMCR_C             (1 << 2)  /* Reset cycle counter (PMCCNTR) to zero */
+#define PMCR_D             (1 << 3)  /* Enable cycle counter clock (PMCCNTR) divider */
+#define PMCR_X             (1 << 4)  /* Export of events is enabled */
+#define PMCR_DP            (1 << 5)  /* Disable PMCCNTR if event counting is prohibited */
+#define PMCR_N_SHIFT       (11)      /* Bits 11-15:  Number of event counters */
+#define PMCR_N_MASK        (0x1f << PMCR_N_SHIFT)
+#define PMCR_IDCODE_SHIFT  (16)      /* Bits 16-23: Identification code */
+#define PMCR_IDCODE_MASK   (0xff << PMCR_IDCODE_SHIFT)
+#define PMCR_IMP_SHIFT     (24)      /* Bits 24-31: Implementer code */
+#define PMCR_IMP_MASK      (0xff << PMCR_IMP_SHIFT)
 
 /* 32-bit Performance Monitors Count Enable Set register (PMCNTENSET):
  * CRn=c9, opc1=0, CRm=c12, opc2=1
diff --git a/arch/arm/src/tms570/tms570_boot.c b/arch/arm/src/tms570/tms570_boot.c
index 363a3a6c5d..c96c0fec61 100644
--- a/arch/arm/src/tms570/tms570_boot.c
+++ b/arch/arm/src/tms570/tms570_boot.c
@@ -105,7 +105,7 @@
 static inline void tms570_event_export(void)
 {
   uint32_t pmcr = cp15_pmu_rdpmcr();
-  pmcr |= PCMR_X;
+  pmcr |= PMCR_X;
   cp15_pmu_wrpmcr(pmcr);
 }
 


[incubator-nuttx] 03/04: arm/cortex-[a|r]: add more functions of Performance Monitors Unit

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 4da48c84ffb97ae6ad2648a33aefb71f6f1f0a8c
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri May 13 17:27:01 2022 +0800

    arm/cortex-[a|r]: add more functions of Performance Monitors Unit
    
    Reference:
    https://developer.arm.com/documentation/ddi0433/a/performance-monitoring-unit/performance-monitoring-register-descriptions
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/arm/src/armv7-a/sctlr.h      | 485 ++++++++++++++++++++++++++++++++++++++
 arch/arm/src/armv7-r/sctlr.h      | 397 ++++++++++++++++++++++++++++++-
 arch/arm/src/tms570/tms570_boot.c |   4 +-
 3 files changed, 871 insertions(+), 15 deletions(-)

diff --git a/arch/arm/src/armv7-a/sctlr.h b/arch/arm/src/armv7-a/sctlr.h
index fb1c666a88..cd8c52d627 100644
--- a/arch/arm/src/armv7-a/sctlr.h
+++ b/arch/arm/src/armv7-a/sctlr.h
@@ -283,6 +283,137 @@
 
 /* TODO: To be provided */
 
+/* CP15 c9 Registers ********************************************************/
+
+/* 32-bit Performance Monitors Control Register (PMCR):
+ * CRn=c9, opc1=0, CRm=c12, opc2=0
+ */
+
+#define PMCR_E             (1 << 0)  /* Enable all counters */
+#define PMCR_P             (1 << 1)  /* Reset all counter events (except PMCCNTR) */
+#define PMCR_C             (1 << 2)  /* Reset cycle counter (PMCCNTR) to zero */
+#define PMCR_D             (1 << 3)  /* Enable cycle counter clock (PMCCNTR) divider */
+#define PMCR_X             (1 << 4)  /* Export of events is enabled */
+#define PMCR_DP            (1 << 5)  /* Disable PMCCNTR if event counting is prohibited */
+#define PMCR_N_SHIFT       (11)      /* Bits 11-15:  Number of event counters */
+#define PMCR_N_MASK        (0x1f << PMCR_N_SHIFT)
+#define PMCR_IDCODE_SHIFT  (16)      /* Bits 16-23: Identification code */
+#define PMCR_IDCODE_MASK   (0xff << PMCR_IDCODE_SHIFT)
+#define PMCR_IMP_SHIFT     (24)      /* Bits 24-31: Implementer code */
+#define PMCR_IMP_MASK      (0xff << PMCR_IMP_SHIFT)
+
+/* 32-bit Performance Monitors Count Enable Set register (PMCNTENSET):
+ * CRn=c9, opc1=0, CRm=c12, opc2=1
+ */
+
+#define PMCESR_CCES        (1 << 31) /* Bits 31: Count Enable Set Register */
+
+/* 32-bit Performance Monitors Count Enable Clear register (PMCNTENCLR):
+ * CRn=c9, opc1=0, CRm=c12, opc2=2
+ */
+
+#define PMCECR_CCEC        (1 << 31) /* Bits 31: Count Enable Clear Register */
+
+/* 32-bit Performance Monitors Overflow Flag Status Register (PMOVSR):
+ * CRn=c9, opc1=0, CRm=c12, opc2=3
+ */
+
+#define PMOFSR_COF0        (1 << 0)  /* Bits  0: Counter 0 overflow flag */
+#define PMOFSR_COF1        (1 << 1)  /* Bits  1: Counter 1 overflow flag */
+#define PMOFSR_COF2        (1 << 2)  /* Bits  2: Counter 2 overflow flag */
+#define PMOFSR_COF3        (1 << 3)  /* Bits  3: Counter 3 overflow flag */
+#define PMOFSR_COF4        (1 << 4)  /* Bits  4: Counter 4 overflow flag */
+#define PMOFSR_COF5        (1 << 5)  /* Bits  5: Counter 5 overflow flag */
+#define PMOFSR_CCOF        (1 << 31) /* Bits 31: Cycle counter overflow flag */
+
+/* 32-bit Performance Monitors Software Increment register (PMSWINC):
+ * CRn=c9, opc1=0, CRm=c12, opc2=4
+ * TODO: To be provided
+ */
+
+/* 32-bit Performance Monitors Event Counter Selection Register (PMSELR):
+ * CRn=c9, opc1=0, CRm=c12, opc2=5
+ */
+
+#define PMECSR_CS_MASK     (0x1f)    /* Bits 0-5: Counter select */
+
+/* 32-bit Performance Monitors Common Event Identification (PMCEID0):
+ * CRn=c9, opc1=0, CRm=c12, opc2=6
+ * TODO: To be provided
+ */
+
+/* 32-bit Performance Monitors Common Event Identification (PMCEID1):
+ * CRn=c9, opc1=0, CRm=c12, opc2=7
+ * TODO: To be provided
+ */
+
+/* 32-bit Performance Monitors Cycle Count Register (PMCCNTR):
+ * CRn=c9, opc1=0, CRm=c13, opc2=0
+ * TODO: To be provided
+ */
+
+/* 32-bit Performance Monitors Event Type Select Register (PMETSR):
+ * CRn=c9, opc1=0, CRm=c13, opc2=1
+ */
+
+#define PMETSR_L1_IC_FILL             (0x1)  /* Level 1 instruction cache refill */
+#define PMETSR_L1_ITLB_FILL           (0x2)  /* Level 1 instruction TLB refill */
+#define PMETSR_L1_DC_FILL             (0x3)  /* Level 1 data cache refill */
+#define PMETSR_L1_DC_ACC              (0x4)  /* Level 1 data cache access */
+#define PMETSR_L1_DTLB_FILL           (0x5)  /* Level 1 data TLB refill */
+#define PMETSR_LOAD                   (0x6)  /* Data read architecturally executed */
+#define PMETSR_STORE                  (0x7)  /* Data write architecturally executed */
+#define PMETSR_INSTARCHEXEC           (0x8)  /* Instruction architecturally executed */
+#define PMETSR_EXCEPETIONTAKEN        (0x9)  /* Exception taken */
+#define PMETSR_EXCEPETIONRET          (0xa)  /* Exception return */
+#define PMETSR_WRCONTEXTIDR           (0xb)  /* Write to CONTEXTIDR */
+#define PMETSR_SOFTPCCHANGE           (0xc)  /* Software change of the PC */
+#define PMETSR_IMMBR                  (0xd)  /* Immediate branch */
+#define PMETSR_PROCRET                (0xe)  /* Procedure return */
+#define PMETSR_UNALINGEDLDSTR         (0xf)  /* Unaligned load or store */
+#define PMETSR_MISPREDICTEDBRANCHEXEC (0x10) /* Mispredicted or not predicted branch speculatively executed */
+#define PMETSR_PREDICTEDBRANCHEXEC    (0x12) /* Predictable branch speculatively executed */
+#define PMETSR_DATAMEMACC             (0x13) /* Data memory access. */
+#define PMETSR_ICACC                  (0x14) /* Instruction Cache access. */
+#define PMETSR_DCEVICTION             (0x15) /* Data cache eviction. */
+#define PMETSR_IRQEXCEPTION           (0x86) /* IRQ exception taken. */
+#define PMETSR_FIQEXCEPTION           (0x87) /* FIQ exception taken. */
+#define PMETSR_EXTMEMREQ              (0xc0) /* External memory request. */
+#define PMETSR_NCEXTMEMREQ            (0xc1) /* Non-cacheable external memory request */
+#define PMETSR_PREFETCHLINEFILL       (0xc2) /* Linefill because of prefetch. */
+#define PMETSR_PREFETCHLINEDROP       (0xc3) /* Prefetch linefill dropped. */
+#define PMETSR_ENTERINGRAMODE         (0xc4) /* Entering read allocate mode. */
+#define PMETSR_RAMODE                 (0xc5) /* Read allocate mode. */
+#define PMETSR_RESERVED               (0xc6) /* Reserved, do not use */
+#define PMETSR_DWSTALLSBFFULL         (0xc9) /* Data Write operation that stalls the pipeline because the store buffer is full. */
+#define PMETSR_EVENT_MASK             (0xff)
+
+/* 32-bit Performance Monitors Event Count Register (PMXEVCNTR):
+ * CRn=c9, opc1=0, CRm=c13, opc2=2
+ * TODO: To be provided
+ */
+
+/* 32-bit Performance Monitors User Enable Register (PMUSERENR):
+ * CRn=c9, opc1=0, CRm=c14, opc2=0
+ */
+
+#define PMUER_UME_SHIFT      (0)       /* Bits 0: User mode enable */
+#define PMUER_UME            (1 << PMUER_UME_SHIFT)
+
+/* 32-bit Performance Monitors Interrupt Enable Set register (PMINTENSET):
+ * CRn=c9, opc1=0, CRm=c14, opc2=1
+ */
+
+#define PMIESR_CCNTOIE_SHIFT (31)    /* Bits 31: CCNT overflow interrupt enable. */
+#define PMIESR_CCNTOIE       (1 << PMIESR_CCNTOIE_SHIFT)
+
+/* 32-bit Performance Monitors Interrupt Enable Clear register (PMINTENCLR):
+ * CRn=c9, opc1=0, CRm=c14, opc2=2
+ */
+
+#define PMIECR_CCNTOIE_SHIFT (31)    /* Bits 31: CCNT overflow interrupt enable. */
+#define PMIECR_CCNTOIE       (1 << PMIECR_CCNTOIE_SHIFT)
+
 /****************************************************************************
  * Assembly Macros
  ****************************************************************************/
@@ -414,6 +545,360 @@ static inline void cp15_wrvbar(unsigned int sctlr)
     );
 }
 
+/****************************************************************************
+ * Name: cp15_pmu_rdpmcr/cp15_pmu_wrpmcr/cp15_pmu_pmcr
+ *
+ * Description:
+ *   Read/Write the Performance Monitor Control Register (PMCR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdpmcr(void)
+{
+  unsigned int pmcr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 0\n"
+      : "=r" (pmcr)
+      :
+      : "memory"
+    );
+
+  return pmcr;
+}
+
+static inline void cp15_pmu_wrpmcr(unsigned int pmcr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 0\n"
+      :
+      : "r" (pmcr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_pmcr(unsigned int pmcr)
+{
+  cp15_pmu_wrpmcr(pmcr | cp15_pmu_rdpmcr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcesr/cp15_pmu_wrcesr/cp15_pmu_cesr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Count Enable Set register (PMCNTENSET)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdcesr(void)
+{
+  unsigned int cesr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 1\n"
+      : "=r" (cesr)
+      :
+      : "memory"
+    );
+
+  return cesr;
+}
+
+static inline void cp15_pmu_wrcesr(unsigned int cesr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 1\n"
+      :
+      : "r" (cesr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_cesr(unsigned int cesr)
+{
+  cp15_pmu_wrcesr(cesr | cp15_pmu_rdcesr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcecr/cp15_pmu_wrcecr/cp15_pmu_cecr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Count Enable Clear register (PMCNTENCLR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdcecr(void)
+{
+  unsigned int cecr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 2\n"
+      : "=r" (cecr)
+      :
+      : "memory"
+    );
+
+  return cecr;
+}
+
+static inline void cp15_pmu_wrcecr(unsigned int cecr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 2\n"
+      :
+      : "r" (cecr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_cecr(unsigned int cecr)
+{
+  cp15_pmu_wrcecr(cecr | cp15_pmu_rdcecr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcecr/cp15_pmu_wrcecr/cp15_pmu_cecr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Overflow Flag Status Register (PMOVSR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdofsr(void)
+{
+  unsigned int ofsr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 3\n"
+      : "=r" (ofsr)
+      :
+      : "memory"
+    );
+
+  return ofsr;
+}
+
+static inline void cp15_pmu_wrofsr(unsigned int ofsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 3\n"
+      :
+      : "r" (ofsr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_ofsr(unsigned int ofsr)
+{
+  cp15_pmu_wrofsr(ofsr | cp15_pmu_rdofsr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdsir/cp15_pmu_wrsir/cp15_pmu_sir
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Software Increment register (PMSWINC)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdsir(void)
+{
+  unsigned int sir;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 4\n"
+      : "=r" (sir)
+      :
+      : "memory"
+    );
+
+  return sir;
+}
+
+static inline void cp15_pmu_wrsir(unsigned int sir)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 4\n"
+      :
+      : "r" (sir)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_sir(unsigned int sir)
+{
+  cp15_pmu_wrsir(sir | cp15_pmu_rdsir());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wrecsr
+ *
+ * Description:
+ *   Write the Performance Monitors Event Counter Selection Register (PMSELR)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wrecsr(unsigned int ecsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 5\n"
+      :
+      : "r" (ecsr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wretsr
+ *
+ * Description:
+ *   Write the Performance Monitors Event Type Select Register (PMXEVTYPER)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wretsr(unsigned int etsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c13, 1\n"
+      :
+      : "r" (etsr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wruer
+ *
+ * Description:
+ *   Write the Performance Monitors User Enable Register (PMUSERENR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rduer(void)
+{
+  unsigned int uer;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c14, 0\n"
+      : "=r" (uer)
+      :
+      : "memory"
+    );
+
+  return uer;
+}
+
+static inline void cp15_pmu_wruer(unsigned int uer)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 0\n"
+      :
+      : "r" (uer)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_uer(unsigned int uer)
+{
+  cp15_pmu_wruer(uer | cp15_pmu_rduer());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wriesr
+ *
+ * Description:
+ *   Write the Performance Monitors
+ *   Interrupt Enable Set register (PMINTENSET)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wriesr(unsigned int iesr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 1\n"
+      :
+      : "r" (iesr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wriecr
+ *
+ * Description:
+ *   Write the Performance Monitors
+ *   Interrupt Enable Clear register (PMINTENCLR)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wriecr(unsigned int iecr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 2\n"
+      :
+      : "r" (iecr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdccr
+ *
+ * Description:
+ *   Read the Performance Monitors Cycle Count Register (PMCCNTR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdccr(void)
+{
+  unsigned int ccr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c13, 0\n"
+      : "=r" (ccr)
+      :
+      : "memory"
+    );
+
+  return ccr;
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdecr
+ *
+ * Description:
+ *   Read the Performance Monitors Event Count Register (PMXEVCNTR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdecr(void)
+{
+  unsigned int ecr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c13, 2"
+      : "=r" (ecr)
+      :
+      : "memory"
+    );
+
+  return ecr;
+}
+
 #endif /* __ASSEMBLY__ */
 
 /****************************************************************************
diff --git a/arch/arm/src/armv7-r/sctlr.h b/arch/arm/src/armv7-r/sctlr.h
index 8974ce1c45..b5497f96cc 100644
--- a/arch/arm/src/armv7-r/sctlr.h
+++ b/arch/arm/src/armv7-r/sctlr.h
@@ -248,11 +248,10 @@
 
 /* 32-bit Performance Monitors Control Register (PMCR):
  * CRn=c9, opc1=0, CRm=c12, opc2=0
- * TODO: To be provided
  */
 
 #define PMCR_E             (1 << 0)  /* Enable all counters */
-#define PMCR_P             (1 << 1)  /* Reset all counter eventts (except PMCCNTR) */
+#define PMCR_P             (1 << 1)  /* Reset all counter events (except PMCCNTR) */
 #define PMCR_C             (1 << 2)  /* Reset cycle counter (PMCCNTR) to zero */
 #define PMCR_D             (1 << 3)  /* Enable cycle counter clock (PMCCNTR) divider */
 #define PMCR_X             (1 << 4)  /* Export of events is enabled */
@@ -266,19 +265,28 @@
 
 /* 32-bit Performance Monitors Count Enable Set register (PMCNTENSET):
  * CRn=c9, opc1=0, CRm=c12, opc2=1
- * TODO: To be provided
  */
 
+#define PMCESR_CCES        (1 << 31) /* Bits 31: Count Enable Set Register */
+
 /* 32-bit Performance Monitors Count Enable Clear register (PMCNTENCLR):
  * CRn=c9, opc1=0, CRm=c12, opc2=2
- * TODO: To be provided
  */
 
+#define PMCECR_CCEC        (1 << 31) /* Bits 31: Count Enable Clear Register */
+
 /* 32-bit Performance Monitors Overflow Flag Status Register (PMOVSR):
  * CRn=c9, opc1=0, CRm=c12, opc2=3
- * TODO: To be provided
  */
 
+#define PMOFSR_COF0        (1 << 0)  /* Bits  0: Counter 0 overflow flag */
+#define PMOFSR_COF1        (1 << 1)  /* Bits  1: Counter 1 overflow flag */
+#define PMOFSR_COF2        (1 << 2)  /* Bits  2: Counter 2 overflow flag */
+#define PMOFSR_COF3        (1 << 3)  /* Bits  3: Counter 3 overflow flag */
+#define PMOFSR_COF4        (1 << 4)  /* Bits  4: Counter 4 overflow flag */
+#define PMOFSR_COF5        (1 << 5)  /* Bits  5: Counter 5 overflow flag */
+#define PMOFSR_CCOF        (1 << 31) /* Bits 31: Cycle counter overflow flag */
+
 /* 32-bit Performance Monitors Software Increment register (PMSWINC):
  * CRn=c9, opc1=0, CRm=c12, opc2=4
  * TODO: To be provided
@@ -286,9 +294,10 @@
 
 /* 32-bit Performance Monitors Event Counter Selection Register (PMSELR):
  * CRn=c9, opc1=0, CRm=c12, opc2=5
- * TODO: To be provided
  */
 
+#define PMECSR_CS_MASK     (0x1f)    /* Bits 0-5: Counter select */
+
 /* 32-bit Performance Monitors Common Event Identification (PMCEID0):
  * CRn=c9, opc1=0, CRm=c12, opc2=6
  * TODO: To be provided
@@ -304,11 +313,42 @@
  * TODO: To be provided
  */
 
-/* 32-bit Performance Monitors Event Type Select Register (PMXEVTYPER):
+/* 32-bit Performance Monitors Event Type Select Register (PMETSR):
  * CRn=c9, opc1=0, CRm=c13, opc2=1
- * TODO: To be provided
  */
 
+#define PMETSR_L1_IC_FILL             (0x1)  /* Level 1 instruction cache refill */
+#define PMETSR_L1_ITLB_FILL           (0x2)  /* Level 1 instruction TLB refill */
+#define PMETSR_L1_DC_FILL             (0x3)  /* Level 1 data cache refill */
+#define PMETSR_L1_DC_ACC              (0x4)  /* Level 1 data cache access */
+#define PMETSR_L1_DTLB_FILL           (0x5)  /* Level 1 data TLB refill */
+#define PMETSR_LOAD                   (0x6)  /* Data read architecturally executed */
+#define PMETSR_STORE                  (0x7)  /* Data write architecturally executed */
+#define PMETSR_INSTARCHEXEC           (0x8)  /* Instruction architecturally executed */
+#define PMETSR_EXCEPETIONTAKEN        (0x9)  /* Exception taken */
+#define PMETSR_EXCEPETIONRET          (0xa)  /* Exception return */
+#define PMETSR_WRCONTEXTIDR           (0xb)  /* Write to CONTEXTIDR */
+#define PMETSR_SOFTPCCHANGE           (0xc)  /* Software change of the PC */
+#define PMETSR_IMMBR                  (0xd)  /* Immediate branch */
+#define PMETSR_PROCRET                (0xe)  /* Procedure return */
+#define PMETSR_UNALINGEDLDSTR         (0xf)  /* Unaligned load or store */
+#define PMETSR_MISPREDICTEDBRANCHEXEC (0x10) /* Mispredicted or not predicted branch speculatively executed */
+#define PMETSR_PREDICTEDBRANCHEXEC    (0x12) /* Predictable branch speculatively executed */
+#define PMETSR_DATAMEMACC             (0x13) /* Data memory access. */
+#define PMETSR_ICACC                  (0x14) /* Instruction Cache access. */
+#define PMETSR_DCEVICTION             (0x15) /* Data cache eviction. */
+#define PMETSR_IRQEXCEPTION           (0x86) /* IRQ exception taken. */
+#define PMETSR_FIQEXCEPTION           (0x87) /* FIQ exception taken. */
+#define PMETSR_EXTMEMREQ              (0xc0) /* External memory request. */
+#define PMETSR_NCEXTMEMREQ            (0xc1) /* Non-cacheable external memory request */
+#define PMETSR_PREFETCHLINEFILL       (0xc2) /* Linefill because of prefetch. */
+#define PMETSR_PREFETCHLINEDROP       (0xc3) /* Prefetch linefill dropped. */
+#define PMETSR_ENTERINGRAMODE         (0xc4) /* Entering read allocate mode. */
+#define PMETSR_RAMODE                 (0xc5) /* Read allocate mode. */
+#define PMETSR_RESERVED               (0xc6) /* Reserved, do not use */
+#define PMETSR_DWSTALLSBFFULL         (0xc9) /* Data Write operation that stalls the pipeline because the store buffer is full. */
+#define PMETSR_EVENT_MASK             (0xff)
+
 /* 32-bit Performance Monitors Event Count Register (PMXEVCNTR):
  * CRn=c9, opc1=0, CRm=c13, opc2=2
  * TODO: To be provided
@@ -316,19 +356,25 @@
 
 /* 32-bit Performance Monitors User Enable Register (PMUSERENR):
  * CRn=c9, opc1=0, CRm=c14, opc2=0
- * TODO: To be provided
  */
 
+#define PMUER_UME_SHIFT      (0)       /* Bits 0: User mode enable */
+#define PMUER_UME            (1 << PMUER_UME_SHIFT)
+
 /* 32-bit Performance Monitors Interrupt Enable Set register (PMINTENSET):
  * CRn=c9, opc1=0, CRm=c14, opc2=1
- * TODO: To be provided
  */
 
+#define PMIESR_CCNTOIE_SHIFT (31)    /* Bits 31: CCNT overflow interrupt enable. */
+#define PMIESR_CCNTOIE       (1 << PMIESR_CCNTOIE_SHIFT)
+
 /* 32-bit Performance Monitors Interrupt Enable Clear register (PMINTENCLR):
  * CRn=c9, opc1=0, CRm=c14, opc2=2
- * TODO: To be provided
  */
 
+#define PMIECR_CCNTOIE_SHIFT (31)    /* Bits 31: CCNT overflow interrupt enable. */
+#define PMIECR_CCNTOIE       (1 << PMIECR_CCNTOIE_SHIFT)
+
 /* CP15 c10 Registers *******************************************************/
 
 /* Not used on ARMv7-R */
@@ -524,7 +570,13 @@ static inline void cp15_wractlr(unsigned int actlr)
     );
 }
 
-/* Read/write the Performance Monitor Control Register (PMCR) */
+/****************************************************************************
+ * Name: cp15_pmu_rdpmcr/cp15_pmu_wrpmcr/cp15_pmu_pmcr
+ *
+ * Description:
+ *   Read/Write the Performance Monitor Control Register (PMCR)
+ *
+ ****************************************************************************/
 
 static inline unsigned int cp15_pmu_rdpmcr(void)
 {
@@ -551,6 +603,327 @@ static inline void cp15_pmu_wrpmcr(unsigned int pmcr)
     );
 }
 
+static inline void cp15_pmu_pmcr(unsigned int pmcr)
+{
+  cp15_pmu_wrpmcr(pmcr | cp15_pmu_rdpmcr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcesr/cp15_pmu_wrcesr/cp15_pmu_cesr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Count Enable Set register (PMCNTENSET)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdcesr(void)
+{
+  unsigned int cesr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 1\n"
+      : "=r" (cesr)
+      :
+      : "memory"
+    );
+
+  return cesr;
+}
+
+static inline void cp15_pmu_wrcesr(unsigned int cesr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 1\n"
+      :
+      : "r" (cesr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_cesr(unsigned int cesr)
+{
+  cp15_pmu_wrcesr(cesr | cp15_pmu_rdcesr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcecr/cp15_pmu_wrcecr/cp15_pmu_cecr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Count Enable Clear register (PMCNTENCLR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdcecr(void)
+{
+  unsigned int cecr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 2\n"
+      : "=r" (cecr)
+      :
+      : "memory"
+    );
+
+  return cecr;
+}
+
+static inline void cp15_pmu_wrcecr(unsigned int cecr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 2\n"
+      :
+      : "r" (cecr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_cecr(unsigned int cecr)
+{
+  cp15_pmu_wrcecr(cecr | cp15_pmu_rdcecr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdcecr/cp15_pmu_wrcecr/cp15_pmu_cecr
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Overflow Flag Status Register (PMOVSR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdofsr(void)
+{
+  unsigned int ofsr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 3\n"
+      : "=r" (ofsr)
+      :
+      : "memory"
+    );
+
+  return ofsr;
+}
+
+static inline void cp15_pmu_wrofsr(unsigned int ofsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 3\n"
+      :
+      : "r" (ofsr)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_ofsr(unsigned int ofsr)
+{
+  cp15_pmu_wrofsr(ofsr | cp15_pmu_rdofsr());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdsir/cp15_pmu_wrsir/cp15_pmu_sir
+ *
+ * Description:
+ *   Read/Write the Performance Monitors
+ *   Software Increment register (PMSWINC)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdsir(void)
+{
+  unsigned int sir;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c12, 4\n"
+      : "=r" (sir)
+      :
+      : "memory"
+    );
+
+  return sir;
+}
+
+static inline void cp15_pmu_wrsir(unsigned int sir)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 4\n"
+      :
+      : "r" (sir)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_sir(unsigned int sir)
+{
+  cp15_pmu_wrsir(sir | cp15_pmu_rdsir());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wrecsr
+ *
+ * Description:
+ *   Write the Performance Monitors Event Counter Selection Register (PMSELR)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wrecsr(unsigned int ecsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c12, 5\n"
+      :
+      : "r" (ecsr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wretsr
+ *
+ * Description:
+ *   Write the Performance Monitors Event Type Select Register (PMETSR)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wretsr(unsigned int etsr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c13, 1\n"
+      :
+      : "r" (etsr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wruer
+ *
+ * Description:
+ *   Write the Performance Monitors User Enable Register (PMUSERENR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rduer(void)
+{
+  unsigned int uer;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c14, 0\n"
+      : "=r" (uer)
+      :
+      : "memory"
+    );
+
+  return uer;
+}
+
+static inline void cp15_pmu_wruer(unsigned int uer)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 0\n"
+      :
+      : "r" (uer)
+      : "memory"
+    );
+}
+
+static inline void cp15_pmu_uer(unsigned int uer)
+{
+  cp15_pmu_wruer(uer | cp15_pmu_rduer());
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wriesr
+ *
+ * Description:
+ *   Write the Performance Monitors
+ *   Interrupt Enable Set register (PMINTENSET)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wriesr(unsigned int iesr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 1\n"
+      :
+      : "r" (iesr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_wriecr
+ *
+ * Description:
+ *   Write the Performance Monitors
+ *   Interrupt Enable Clear register (PMINTENCLR)
+ *
+ ****************************************************************************/
+
+static inline void cp15_pmu_wriecr(unsigned int iecr)
+{
+  __asm__ __volatile__
+    (
+      "\tmcr p15, 0, %0, c9, c14, 2\n"
+      :
+      : "r" (iecr)
+      : "memory"
+    );
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdccr
+ *
+ * Description:
+ *   Read the Performance Monitors Cycle Count Register (PMCCNTR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdccr(void)
+{
+  unsigned int ccr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c13, 0\n"
+      : "=r" (ccr)
+      :
+      : "memory"
+    );
+
+  return ccr;
+}
+
+/****************************************************************************
+ * Name: cp15_pmu_rdecr
+ *
+ * Description:
+ *   Read the Performance Monitors Event Count Register (PMXEVCNTR)
+ *
+ ****************************************************************************/
+
+static inline unsigned int cp15_pmu_rdecr(void)
+{
+  unsigned int ecr;
+  __asm__ __volatile__
+    (
+      "\tmrc p15, 0, %0, c9, c13, 2"
+      : "=r" (ecr)
+      :
+      : "memory"
+    );
+
+  return ecr;
+}
+
 #endif /* __ASSEMBLY__ */
 
 /****************************************************************************
diff --git a/arch/arm/src/tms570/tms570_boot.c b/arch/arm/src/tms570/tms570_boot.c
index c96c0fec61..51fc8d51bd 100644
--- a/arch/arm/src/tms570/tms570_boot.c
+++ b/arch/arm/src/tms570/tms570_boot.c
@@ -104,9 +104,7 @@
 
 static inline void tms570_event_export(void)
 {
-  uint32_t pmcr = cp15_pmu_rdpmcr();
-  pmcr |= PMCR_X;
-  cp15_pmu_wrpmcr(pmcr);
+  cp15_pmu_pmcr(PMCR_X);
 }
 
 /****************************************************************************


[incubator-nuttx] 04/04: arm/cortex-[a|r]: add performance counter implement

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 701e56d4aede376ce179a65d3b2fbfed162c886b
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri May 13 20:28:32 2022 +0800

    arm/cortex-[a|r]: add performance counter implement
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/arm/src/armv7-a/Make.defs  |  1 +
 arch/arm/src/armv7-a/arm_perf.c | 87 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/src/armv7-r/Make.defs  |  1 +
 arch/arm/src/armv7-r/arm_perf.c | 87 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+)

diff --git a/arch/arm/src/armv7-a/Make.defs b/arch/arm/src/armv7-a/Make.defs
index e0809db2c1..54f85e19de 100644
--- a/arch/arm/src/armv7-a/Make.defs
+++ b/arch/arm/src/armv7-a/Make.defs
@@ -49,6 +49,7 @@ CMN_CSRCS += arm_doirq.c arm_gicv2.c arm_gicv2_dump.c
 CMN_CSRCS += arm_initialstate.c arm_mmu.c arm_prefetchabort.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
+CMN_CSRCS += arm_perf.c
 
 ifeq ($(CONFIG_ARMV7A_L2CC_PL310),y)
   CMN_CSRCS += arm_l2cc_pl310.c
diff --git a/arch/arm/src/armv7-a/arm_perf.c b/arch/arm/src/armv7-a/arm_perf.c
new file mode 100644
index 0000000000..83af327986
--- /dev/null
+++ b/arch/arm/src/armv7-a/arm_perf.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/arm/src/armv7-a/arm_perf.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/arch.h>
+#include <nuttx/clock.h>
+
+#include "arm_internal.h"
+#include "sctlr.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint32_t g_cpu_freq;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_perf_*
+ *
+ * Description:
+ *   The first interface simply provides the current time value in unknown
+ *   units.  NOTE:  This function may be called early before the timer has
+ *   been initialized.  In that event, the function should just return a
+ *   start time of zero.
+ *
+ *   Nothing is assumed about the units of this time value.  The following
+ *   are assumed, however: (1) The time is an unsigned integer value, (2)
+ *   the time is monotonically increasing, and (3) the elapsed time (also
+ *   in unknown units) can be obtained by subtracting a start time from
+ *   the current time.
+ *
+ *   The second interface simple converts an elapsed time into well known
+ *   units.
+ *
+ ****************************************************************************/
+
+void up_perf_init(void *arg)
+{
+  g_cpu_freq = (uint32_t)(uintptr_t)arg;
+
+  cp15_pmu_uer(PMUER_UME);
+  cp15_pmu_pmcr(PMCR_E);
+  cp15_pmu_cesr(PMCESR_CCES);
+}
+
+uint32_t up_perf_getfreq(void)
+{
+  return g_cpu_freq;
+}
+
+uint32_t up_perf_gettime(void)
+{
+  return cp15_pmu_rdccr();
+}
+
+void up_perf_convert(uint32_t elapsed, struct timespec *ts)
+{
+  uint32_t left;
+
+  ts->tv_sec  = elapsed / g_cpu_freq;
+  left        = elapsed - ts->tv_sec * g_cpu_freq;
+  ts->tv_nsec = NSEC_PER_SEC * (uint64_t)left / g_cpu_freq;
+}
diff --git a/arch/arm/src/armv7-r/Make.defs b/arch/arm/src/armv7-r/Make.defs
index 2989a9686e..5c106ebea4 100644
--- a/arch/arm/src/armv7-r/Make.defs
+++ b/arch/arm/src/armv7-r/Make.defs
@@ -33,6 +33,7 @@ CMN_CSRCS += arm_cache.c arm_dataabort.c arm_doirq.c arm_gicv2.c
 CMN_CSRCS += arm_initialstate.c arm_prefetchabort.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
+CMN_CSRCS += arm_perf.c
 
 # Common C source files
 
diff --git a/arch/arm/src/armv7-r/arm_perf.c b/arch/arm/src/armv7-r/arm_perf.c
new file mode 100644
index 0000000000..0f56dc369e
--- /dev/null
+++ b/arch/arm/src/armv7-r/arm_perf.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/arm/src/armv7-r/arm_perf.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/arch.h>
+#include <nuttx/clock.h>
+
+#include "arm_internal.h"
+#include "sctlr.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint32_t g_cpu_freq;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_perf_*
+ *
+ * Description:
+ *   The first interface simply provides the current time value in unknown
+ *   units.  NOTE:  This function may be called early before the timer has
+ *   been initialized.  In that event, the function should just return a
+ *   start time of zero.
+ *
+ *   Nothing is assumed about the units of this time value.  The following
+ *   are assumed, however: (1) The time is an unsigned integer value, (2)
+ *   the time is monotonically increasing, and (3) the elapsed time (also
+ *   in unknown units) can be obtained by subtracting a start time from
+ *   the current time.
+ *
+ *   The second interface simple converts an elapsed time into well known
+ *   units.
+ *
+ ****************************************************************************/
+
+void up_perf_init(void *arg)
+{
+  g_cpu_freq = (uint32_t)(uintptr_t)arg;
+
+  cp15_pmu_uer(PMUER_UME);
+  cp15_pmu_pmcr(PMCR_E);
+  cp15_pmu_cesr(PMCESR_CCES);
+}
+
+uint32_t up_perf_getfreq(void)
+{
+  return g_cpu_freq;
+}
+
+uint32_t up_perf_gettime(void)
+{
+  return cp15_pmu_rdccr();
+}
+
+void up_perf_convert(uint32_t elapsed, struct timespec *ts)
+{
+  uint32_t left;
+
+  ts->tv_sec  = elapsed / g_cpu_freq;
+  left        = elapsed - ts->tv_sec * g_cpu_freq;
+  ts->tv_nsec = NSEC_PER_SEC * (uint64_t)left / g_cpu_freq;
+}