[rtems commit] bsps/arm: Use Global Timer for Cortex-A9 MPCore

Sebastian Huber sebh at rtems.org
Mon Feb 10 15:52:13 UTC 2014


Module:    rtems
Branch:    master
Commit:    0df8d7f20d1e1e0cddf52f3338989f4fdf2cd8ad
Changeset: http://git.rtems.org/rtems/commit/?id=0df8d7f20d1e1e0cddf52f3338989f4fdf2cd8ad

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Feb 10 12:21:24 2014 +0100

bsps/arm: Use Global Timer for Cortex-A9 MPCore

Use the Global Timer for the Cortex-A9 MPCore clock driver instead of
the Private Timer.  This enables a consistent nanoseconds since last
context switch value across all processors.

---

 c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h |    2 +
 .../libbsp/arm/shared/arm-a9mpcore-clock-config.c  |   76 +++++++++++++-------
 .../libbsp/arm/shared/include/arm-a9mpcore-regs.h  |   16 +++-
 .../libbsp/arm/shared/include/arm-a9mpcore-start.h |   11 +++
 c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h     |    2 +
 5 files changed, 78 insertions(+), 29 deletions(-)

diff --git a/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h b/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h
index c4f14d4..959ff92 100644
--- a/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h
+++ b/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h
@@ -45,6 +45,8 @@ extern "C" {
 
 #define BSP_ARM_GIC_CPUIF_BASE 0x1f000100
 
+#define BSP_ARM_A9MPCORE_GT_BASE 0x1f000200
+
 #define BSP_ARM_A9MPCORE_PT_BASE 0x1f000600
 
 #define BSP_ARM_GIC_DIST_BASE 0x1f001000
diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c
index de8a193..6f9990c 100644
--- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c
+++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -17,7 +17,7 @@
 #include <bsp/arm-a9mpcore-regs.h>
 #include <bsp/arm-a9mpcore-clock.h>
 
-#define A9MPCORE_PT ((volatile a9mpcore_pt *) BSP_ARM_A9MPCORE_PT_BASE)
+#define A9MPCORE_GT ((volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE)
 
 static uint64_t a9mpcore_clock_last_tick_k;
 
@@ -32,9 +32,9 @@ __attribute__ ((weak)) uint32_t a9mpcore_clock_periphclk(void)
 
 static void a9mpcore_clock_at_tick(void)
 {
-  volatile a9mpcore_pt *pt = A9MPCORE_PT;
+  volatile a9mpcore_gt *gt = A9MPCORE_GT;
 
-  pt->irqst = A9MPCORE_PT_IRQST_EFLG;
+  gt->irqst = A9MPCORE_GT_IRQST_EFLG;
 }
 
 static void a9mpcore_clock_handler_install(void)
@@ -42,7 +42,7 @@ static void a9mpcore_clock_handler_install(void)
   rtems_status_code sc;
 
   sc = rtems_interrupt_handler_install(
-    A9MPCORE_IRQ_PT,
+    A9MPCORE_IRQ_GT,
     "Clock",
     RTEMS_INTERRUPT_UNIQUE,
     (rtems_interrupt_handler) Clock_isr,
@@ -56,31 +56,56 @@ static void a9mpcore_clock_handler_install(void)
   }
 }
 
-static void a9mpcore_clock_initialize(void)
+static uint64_t a9mpcore_clock_get_counter(volatile a9mpcore_gt *gt)
 {
-  volatile a9mpcore_pt *pt = A9MPCORE_PT;
-  uint64_t periphclk = (uint64_t) a9mpcore_clock_periphclk();
-  uint64_t interval = (periphclk
-    * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000;
+  uint32_t cl;
+  uint32_t cu1;
+  uint32_t cu2;
+
+  do {
+    cu1 = gt->cntrupper;
+    cl = gt->cntrlower;
+    cu2 = gt->cntrupper;
+  } while (cu1 != cu2);
 
-  a9mpcore_clock_last_tick_k = (1000000000ULL << 32) / periphclk;
+  return ((uint64_t) cu2 << 32) | cl;
+}
 
-  pt->load = (uint32_t) interval - 1;
-  pt->ctrl = A9MPCORE_PT_CTRL_AUTO_RLD
-    | A9MPCORE_PT_CTRL_IRQ_EN
-    | A9MPCORE_PT_CTRL_TMR_EN;
+static void a9mpcore_clock_initialize(void)
+{
+  volatile a9mpcore_gt *gt = A9MPCORE_GT;
+  uint64_t periphclk = a9mpcore_clock_periphclk();
+  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
+  uint32_t interval = (uint32_t) ((periphclk * us_per_tick) / 1000000);
+  uint64_t cmpval;
+
+  a9mpcore_clock_last_tick_k = (UINT64_C(1000000000) << 32) / periphclk;
+
+  gt->ctrl &= A9MPCORE_GT_CTRL_TMR_EN;
+  gt->irqst = A9MPCORE_GT_IRQST_EFLG;
+
+  cmpval = a9mpcore_clock_get_counter(gt);
+  cmpval += interval;
+
+  gt->cmpvallower = (uint32_t) cmpval;
+  gt->cmpvalupper = (uint32_t) (cmpval >> 32);
+  gt->autoinc = interval;
+  gt->ctrl = A9MPCORE_GT_CTRL_AUTOINC_EN
+    | A9MPCORE_GT_CTRL_IRQ_EN
+    | A9MPCORE_GT_CTRL_COMP_EN
+    | A9MPCORE_GT_CTRL_TMR_EN;
 }
 
 static void a9mpcore_clock_cleanup(void)
 {
-  volatile a9mpcore_pt *pt = A9MPCORE_PT;
+  volatile a9mpcore_gt *gt = A9MPCORE_GT;
   rtems_status_code sc;
 
-  pt->ctrl = 0;
-  pt->irqst = A9MPCORE_PT_IRQST_EFLG;
+  gt->ctrl &= A9MPCORE_GT_CTRL_TMR_EN;
+  gt->irqst = A9MPCORE_GT_IRQST_EFLG;
 
   sc = rtems_interrupt_handler_remove(
-    A9MPCORE_IRQ_PT,
+    A9MPCORE_IRQ_GT,
     (rtems_interrupt_handler) Clock_isr,
     NULL
   );
@@ -94,16 +119,17 @@ static void a9mpcore_clock_cleanup(void)
 
 static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void)
 {
-  volatile a9mpcore_pt *pt = A9MPCORE_PT;
+  volatile a9mpcore_gt *gt = A9MPCORE_GT;
   uint64_t k = a9mpcore_clock_last_tick_k;
-  uint32_t c = pt->cntr;
-  uint32_t p = pt->load + 1;
+  uint32_t c = gt->cntrlower;
+  uint32_t n = gt->cmpvallower;
+  uint32_t i = gt->autoinc;
 
-  if ((pt->irqst & A9MPCORE_PT_IRQST_EFLG) != 0) {
-    c = pt->cntr - p;
+  if ((gt->irqst & A9MPCORE_GT_IRQST_EFLG) != 0) {
+    n = gt->cmpvallower - i;
   }
 
-  return (uint32_t) (((p - c) * k) >> 32);
+  return (uint32_t) (((c - n - i) * k) >> 32);
 }
 
 #define Clock_driver_support_at_tick() \
diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h
index 86bdcb2..0910e4c 100644
--- a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h
+++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h
@@ -58,12 +58,20 @@ typedef struct {
 } a9mpcore_gic;
 
 typedef struct {
-  uint32_t cntr;
-  uint32_t reserved_04;
+  uint32_t cntrlower;
+  uint32_t cntrupper;
+#define A9MPCORE_GT_CTRL_PRESCALER(val) BSP_FLD32(val, 8, 15)
+#define A9MPCORE_GT_CTRL_PRESCALER_GET(reg) BSP_FLD32GET(reg, 8, 15)
+#define A9MPCORE_GT_CTRL_PRESCALER_SET(reg, val) BSP_FLD32SET(reg, val, 8, 15)
+#define A9MPCORE_GT_CTRL_AUTOINC_EN BSP_BIT32(3)
+#define A9MPCORE_GT_CTRL_IRQ_EN BSP_BIT32(2)
+#define A9MPCORE_GT_CTRL_COMP_EN BSP_BIT32(1)
+#define A9MPCORE_GT_CTRL_TMR_EN BSP_BIT32(0)
   uint32_t ctrl;
+#define A9MPCORE_GT_IRQST_EFLG BSP_BIT32(0)
   uint32_t irqst;
-  uint32_t cmpval;
-  uint32_t reserved_14;
+  uint32_t cmpvallower;
+  uint32_t cmpvalupper;
   uint32_t autoinc;
 } a9mpcore_gt;
 
diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h
index a62dcda..9ebc5a5 100644
--- a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h
+++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h
@@ -120,8 +120,19 @@ BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_hook_0(void)
 #endif
 }
 
+BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_global_timer(void)
+{
+  volatile a9mpcore_gt *gt = (volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE;
+
+  gt->ctrl = 0;
+  gt->cntrlower = 0;
+  gt->cntrupper = 0;
+  gt->ctrl = A9MPCORE_GT_CTRL_TMR_EN;
+}
+
 BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_hook_1(void)
 {
+  arm_a9mpcore_start_global_timer();
   arm_a9mpcore_start_set_vector_base();
 }
 
diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h b/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h
index c722d18..56e62a5 100644
--- a/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h
+++ b/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h
@@ -49,6 +49,8 @@ extern "C" {
 
 #define BSP_ARM_GIC_CPUIF_BASE 0xf8f00100
 
+#define BSP_ARM_A9MPCORE_GT_BASE 0xf8f00200
+
 #define BSP_ARM_A9MPCORE_PT_BASE 0xf8f00600
 
 #define BSP_ARM_GIC_DIST_BASE 0xf8f01000




More information about the vc mailing list