Procházet zdrojové kódy

Revert "[libcpu] remove gtimer/pmu from cortex-a"

Wayne před 2 roky
rodič
revize
5d014e8d31

+ 3 - 0
libcpu/arm/cortex-a/SConscript

@@ -8,8 +8,11 @@ cwd     = GetCurrentDir()
 src     = Split('''
 cache.c
 cpu.c
+gtimer.c
 mmu.c
+pmu.c
 stack.c
+
 ''')
 CPPPATH = [cwd]
 

+ 0 - 6
libcpu/arm/cortex-a/armv7.h

@@ -69,10 +69,4 @@ struct rt_hw_stack
 #define E_Bit       (1<<9)
 #define J_Bit       (1<<24)
 
-#define PABT_EXCEPTION 0x1
-#define DABT_EXCEPTION 0x2
-#define UND_EXCEPTION  0x3
-#define SWI_EXCEPTION  0x4
-#define RESV_EXCEPTION 0xF
-
 #endif

+ 179 - 0
libcpu/arm/cortex-a/gtimer.c

@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-03-30     huijie.feng  first version
+ */
+
+#include "cp15.h"
+#include <rtdef.h>
+
+/** Set CNTFRQ
+ *  This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+ *  @param value: CNTFRQ Register value to set
+ */
+static inline void __set_cntfrq(rt_uint32_t value)
+{
+    __set_cp(15, 0, value, 14, 0, 0);
+}
+
+/** Get CNTFRQ
+ *  This function returns the value of the PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+ *  return CNTFRQ Register value
+ */
+static inline rt_uint32_t __get_cntfrq(void)
+{
+    rt_uint32_t result;
+    __get_cp(15, 0, result, 14, 0 , 0);
+    return result;
+}
+
+/** Set CNTP_TVAL
+ *  This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
+ *  param value: CNTP_TVAL Register value to set
+ */
+static inline void __set_cntp_tval(rt_uint32_t value)
+{
+    __set_cp(15, 0, value, 14, 2, 0);
+}
+
+/** Get CNTP_TVAL
+ *  This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
+ *  return CNTP_TVAL Register value
+ */
+static inline rt_uint32_t __get_cntp_tval(void)
+{
+    rt_uint32_t result;
+    __get_cp(15, 0, result, 14, 2, 0);
+    return result;
+}
+
+/** Get CNTPCT
+ *  This function returns the value of the 64 bits PL1 Physical Count Register (CNTPCT).
+ *  return CNTPCT Register value
+ */
+static inline rt_uint64_t __get_cntpct(void)
+{
+    rt_uint64_t result;
+    __get_cp64(15, 0, result, 14);
+    return result;
+}
+
+/** Set CNTP_CVAL
+ *  This function assigns the given value to 64bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+ *  param value: CNTP_CVAL Register value to set
+*/
+static inline void __set_cntp_cval(rt_uint64_t value)
+{
+    __set_cp64(15, 2, value, 14);
+}
+
+/** Get CNTP_CVAL
+ *  This function returns the value of the 64 bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+ *  return CNTP_CVAL Register value
+ */
+static inline rt_uint64_t __get_cntp_cval(void)
+{
+    rt_uint64_t result;
+    __get_cp64(15, 2, result, 14);
+    return result;
+}
+
+/** Set CNTP_CTL
+ *  This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
+ *  param value: CNTP_CTL Register value to set
+ */
+static inline void __set_cntp_ctl(uint32_t value)
+{
+    __set_cp(15, 0, value, 14, 2, 1);
+}
+
+/** Get CNTP_CTL register
+ *  return CNTP_CTL Register value
+ */
+static inline rt_uint32_t __get_cntp_ctl(void)
+{
+    rt_uint32_t result;
+    __get_cp(15, 0, result, 14, 2, 1);
+    return result;
+}
+
+/** Configures the frequency the timer shall run at.
+ *  param value The timer frequency in Hz.
+ */
+void gtimer_set_counter_frequency(rt_uint32_t value)
+{
+    __set_cntfrq(value);
+    __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the frequency the timer shall run at.
+ *  return timer frequency in Hz.
+ */
+rt_uint32_t gtimer_get_counter_frequency(void)
+{
+    return(__get_cntfrq());
+}
+
+/** Sets the reset value of the timer.
+ *  param value: The value the timer is loaded with.
+ */
+void gtimer_set_load_value(rt_uint32_t value)
+{
+    __set_cntp_tval(value);
+    __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the current counter value.
+ *  return Current counter value.
+ */
+rt_uint32_t gtimer_get_current_value(void)
+{
+    return(__get_cntp_tval());
+}
+
+/** Get the current physical counter value.
+ *  return Current physical counter value.
+ */
+rt_uint64_t gtimer_get_current_physical_value(void)
+{
+    return(__get_cntpct());
+}
+
+/** Set the physical compare value.
+ *  param value: New physical timer compare value.
+ */
+void gtimer_set_physical_compare_value(rt_uint64_t value)
+{
+    __set_cntp_cval(value);
+    __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the physical compare value.
+ *  return Physical compare value.
+ */
+rt_uint64_t gtimer_get_physical_compare_value(void)
+{
+    return(__get_cntp_cval());
+}
+
+/** Configure the timer by setting the control value.
+ *  param value: New timer control value.
+ */
+void gtimer_set_control(rt_uint32_t value)
+{
+    __set_cntp_ctl(value);
+    __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the control value.
+ *  return Control value.
+ */
+rt_uint32_t gtimer_get_control(void)
+{
+    return(__get_cntp_ctl());
+}
+

+ 27 - 0
libcpu/arm/cortex-a/gtimer.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-03-30     huijie.feng  first version
+ */
+
+#ifndef __GTIMER_H__
+#define __GTIMER_H__
+
+#include <rtdef.h>
+
+void gtimer_set_counter_frequency(rt_uint32_t value);
+rt_uint32_t gtimer_get_counter_frequency(void);
+void gtimer_set_load_value(rt_uint32_t value);
+rt_uint32_t gtimer_get_current_value(void);
+rt_uint64_t gtimer_get_current_physical_value(void);
+void gtimer_set_physical_compare_value(rt_uint64_t value);
+rt_uint64_t gtimer_get_physical_compare_value(void);
+void gtimer_set_control(rt_uint32_t value);
+rt_uint32_t gtimer_get_control(void);
+
+#endif
+

+ 20 - 0
libcpu/arm/cortex-a/pmu.c

@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+#include <rtthread.h>
+#include "pmu.h"
+
+void rt_hw_pmu_dump_feature(void)
+{
+    unsigned long reg;
+
+    reg = rt_hw_pmu_get_control();
+    rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
+               reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
+    RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
+}

+ 159 - 0
libcpu/arm/cortex-a/pmu.h

@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+#ifndef __PMU_H__
+#define __PMU_H__
+
+#include "board.h"
+
+/* Number of counters */
+#define ARM_PMU_CNTER_NR 4
+
+enum rt_hw_pmu_event_type {
+    ARM_PMU_EVENT_PMNC_SW_INCR      = 0x00,
+    ARM_PMU_EVENT_L1_ICACHE_REFILL  = 0x01,
+    ARM_PMU_EVENT_ITLB_REFILL       = 0x02,
+    ARM_PMU_EVENT_L1_DCACHE_REFILL  = 0x03,
+    ARM_PMU_EVENT_L1_DCACHE_ACCESS  = 0x04,
+    ARM_PMU_EVENT_DTLB_REFILL       = 0x05,
+    ARM_PMU_EVENT_MEM_READ          = 0x06,
+    ARM_PMU_EVENT_MEM_WRITE         = 0x07,
+    ARM_PMU_EVENT_INSTR_EXECUTED    = 0x08,
+    ARM_PMU_EVENT_EXC_TAKEN         = 0x09,
+    ARM_PMU_EVENT_EXC_EXECUTED      = 0x0A,
+    ARM_PMU_EVENT_CID_WRITE         = 0x0B,
+};
+
+/* Enable bit */
+#define ARM_PMU_PMCR_E   (0x01 << 0)
+/* Event counter reset */
+#define ARM_PMU_PMCR_P   (0x01 << 1)
+/* Cycle counter reset */
+#define ARM_PMU_PMCR_C   (0x01 << 2)
+/* Cycle counter divider */
+#define ARM_PMU_PMCR_D   (0x01 << 3)
+
+#ifdef __GNUC__
+rt_inline void rt_hw_pmu_enable_cnt(int divide64)
+{
+    unsigned long pmcr;
+    unsigned long pmcntenset;
+
+    asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+    pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
+    if (divide64)
+        pmcr |= ARM_PMU_PMCR_D;
+    else
+        pmcr &= ~ARM_PMU_PMCR_D;
+    asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+
+    /* enable all the counters */
+    pmcntenset = ~0;
+    asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
+    /* clear overflows(just in case) */
+    asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
+}
+
+rt_inline unsigned long rt_hw_pmu_get_control(void)
+{
+    unsigned long pmcr;
+    asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+    return pmcr;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_ceid(void)
+{
+    unsigned long reg;
+    /* only PMCEID0 is supported, PMCEID1 is RAZ. */
+    asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
+    return reg;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_cnten(void)
+{
+    unsigned long pmcnt;
+    asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
+    return pmcnt;
+}
+
+rt_inline void rt_hw_pmu_reset_cycle(void)
+{
+    unsigned long pmcr;
+
+    asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+    pmcr |= ARM_PMU_PMCR_C;
+    asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+    asm volatile ("isb");
+}
+
+rt_inline void rt_hw_pmu_reset_event(void)
+{
+    unsigned long pmcr;
+
+    asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+    pmcr |= ARM_PMU_PMCR_P;
+    asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+    asm volatile ("isb");
+}
+
+rt_inline unsigned long rt_hw_pmu_get_cycle(void)
+{
+    unsigned long cyc;
+    asm volatile ("isb");
+    asm volatile ("mrc  p15, 0, %0, c9, c13, 0" : "=r"(cyc));
+    return cyc;
+}
+
+rt_inline void rt_hw_pmu_select_counter(int idx)
+{
+    RT_ASSERT(idx < ARM_PMU_CNTER_NR);
+
+    asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
+    /* Linux add an isb here, don't know why here. */
+    asm volatile ("isb");
+}
+
+rt_inline void rt_hw_pmu_select_event(int idx,
+                                      enum rt_hw_pmu_event_type eve)
+{
+    RT_ASSERT(idx < ARM_PMU_CNTER_NR);
+
+    rt_hw_pmu_select_counter(idx);
+    asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
+}
+
+rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
+{
+    unsigned long reg;
+
+    rt_hw_pmu_select_counter(idx);
+    asm volatile ("isb");
+    asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
+    return reg;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
+{
+    unsigned long reg;
+    asm volatile ("isb");
+    asm ("mrc  p15, 0, %0, c9, c12, 3" : "=r"(reg));
+    return reg;
+}
+
+rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
+{
+    asm ("mcr  p15, 0, %0, c9, c12, 3" : : "r"(reg));
+    asm volatile ("isb");
+}
+
+#endif
+
+void rt_hw_pmu_dump_feature(void);
+
+#endif /* end of include guard: __PMU_H__ */
+