[rtems commit] score: Fix simple timecounter support

Sebastian Huber sebh at rtems.org
Wed Jan 27 07:09:41 UTC 2016


Module:    rtems
Branch:    4.11
Commit:    2145853b009e939dfbe14869b710133f50500a26
Changeset: http://git.rtems.org/rtems/commit/?id=2145853b009e939dfbe14869b710133f50500a26

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Dec 23 07:29:47 2015 +0100

score: Fix simple timecounter support

Close #2502.

---

 .../arm/shared/armv7m/clock/armv7m-clock-config.c  | 51 ++++++++++++++++------
 c/src/lib/libbsp/m68k/mcf52235/clock/clock.c       | 19 ++++----
 c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c       | 19 ++++----
 c/src/lib/libbsp/m68k/mcf5329/clock/clock.c        | 19 ++++----
 c/src/lib/libbsp/m68k/uC5282/clock/clock.c         | 51 +++++++++++-----------
 .../libbsp/powerpc/mpc55xxevb/clock/clock-config.c | 34 +++++++++------
 c/src/lib/libbsp/shared/clockdrv_shell.h           | 16 ++++++-
 c/src/lib/libbsp/sparc/erc32/clock/ckinit.c        | 10 +++--
 c/src/lib/libbsp/sparc/leon2/clock/ckinit.c        | 13 ++++--
 c/src/lib/libbsp/sparc/leon3/clock/ckinit.c        | 31 +++++++------
 c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c  | 15 +++----
 c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c      | 32 ++++++++------
 cpukit/rtems/src/clocktick.c                       |  6 ++-
 cpukit/sapi/include/rtems/timecounter.h            | 35 ++++++++++++---
 cpukit/score/include/rtems/score/timecounter.h     | 27 +++++++++++-
 cpukit/score/src/kern_tc.c                         | 16 +++----
 doc/bsp_howto/clock.t                              | 13 +++++-
 17 files changed, 267 insertions(+), 140 deletions(-)

diff --git a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
index e78684c..d481c44 100644
--- a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
+++ b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
@@ -23,7 +23,12 @@
 /* This is defined in clockdrv_shell.h */
 static void Clock_isr(void *arg);
 
-static rtems_timecounter_simple _ARMV7M_TC;
+typedef struct {
+  rtems_timecounter_simple base;
+  bool countflag;
+} ARMV7M_Timecounter;
+
+static ARMV7M_Timecounter _ARMV7M_TC;
 
 static uint32_t _ARMV7M_TC_get(rtems_timecounter_simple *tc)
 {
@@ -32,11 +37,25 @@ static uint32_t _ARMV7M_TC_get(rtems_timecounter_simple *tc)
   return systick->cvr;
 }
 
-static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *tc)
+static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *base)
 {
-  volatile ARMV7M_SCB *scb = _ARMV7M_SCB;
+  ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
+  rtems_interrupt_level level;
+  bool countflag;
+
+  rtems_interrupt_disable(level);
+
+  countflag = tc->countflag;
+  if (!countflag) {
+    volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
+
+    countflag = ((systick->csr & ARMV7M_SYSTICK_CSR_COUNTFLAG) != 0);
+    tc->countflag = countflag;
+  }
+
+  rtems_interrupt_enable(level);
 
-  return ((scb->icsr & ARMV7M_SCB_ICSR_PENDSTSET) != 0);
+  return countflag;
 }
 
 static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *tc)
@@ -48,19 +67,26 @@ static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *tc)
   );
 }
 
-static void _ARMV7M_TC_tick(void)
-{
-  rtems_timecounter_simple_downcounter_tick(&_ARMV7M_TC, _ARMV7M_TC_get);
-}
-
-static void _ARMV7M_Systick_at_tick(void)
+static void _ARMV7M_TC_at_tick(rtems_timecounter_simple *base)
 {
+  ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
   volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
 
+  tc->countflag = false;
+
   /* Clear COUNTFLAG */
   systick->csr;
 }
 
+static void _ARMV7M_TC_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &_ARMV7M_TC.base,
+    _ARMV7M_TC_get,
+    _ARMV7M_TC_at_tick
+  );
+}
+
 static void _ARMV7M_Systick_handler(void)
 {
   _ARMV7M_Interrupt_service_enter();
@@ -95,7 +121,7 @@ static void _ARMV7M_Systick_initialize(void)
     | ARMV7M_SYSTICK_CSR_CLKSOURCE;
 
   rtems_timecounter_simple_install(
-    &_ARMV7M_TC,
+    &_ARMV7M_TC.base,
     freq,
     interval,
     _ARMV7M_TC_get_timecount
@@ -111,9 +137,6 @@ static void _ARMV7M_Systick_cleanup(void)
 
 #define Clock_driver_timecounter_tick() _ARMV7M_TC_tick()
 
-#define Clock_driver_support_at_tick() \
-  _ARMV7M_Systick_at_tick()
-
 #define Clock_driver_support_initialize_hardware() \
   _ARMV7M_Systick_initialize()
 
diff --git a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
index fdc1ed6..4b5f4af 100644
--- a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
@@ -32,18 +32,19 @@ static uint32_t mcf52235_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void mcf52235_tc_tick(void)
+static void mcf52235_tc_at_tick(rtems_timecounter_simple *tc)
 {
-  rtems_timecounter_simple_downcounter_tick(&mcf52235_tc, mcf52235_tc_get);
+  MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
 }
 
-/*
- * Periodic interval timer interrupt handler
- */
-#define Clock_driver_support_at_tick()             \
-    do {                                           \
-        MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;         \
-    } while (0)                                    \
+static void mcf52235_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &mcf52235_tc,
+    mcf52235_tc_get,
+    mcf52235_tc_at_tick
+  );
+}
 
 /*
  * Attach clock interrupt handler
diff --git a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
index 743bd1f..ee97e50 100644
--- a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
@@ -32,18 +32,19 @@ static uint32_t mcf5225x_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void mcf5225x_tc_tick(void)
+static void mcf5225x_tc_at_tick(rtems_timecounter_simple *tc)
 {
-  rtems_timecounter_simple_downcounter_tick(&mcf5225x_tc, mcf5225x_tc_get);
+  MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
 }
 
-/*
- * Periodic interval timer interrupt handler
- */
-#define Clock_driver_support_at_tick()             \
-    do {                                           \
-        MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;         \
-    } while (0)                                    \
+static void mcf5225x_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &mcf5225x_tc,
+    mcf5225x_tc_get,
+    mcf5225x_tc_at_tick
+  );
+}
 
 /*
  * Attach clock interrupt handler
diff --git a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
index 94c5bb0..5741b30 100644
--- a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
@@ -32,18 +32,19 @@ static uint32_t mcf5329_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void mcf5329_tc_tick(void)
+static void mcf5329_tc_at_tick(rtems_timecounter_simple *tc)
 {
-  rtems_timecounter_simple_downcounter_tick(&mcf5329_tc, mcf5329_tc_get);
+  MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;
 }
 
-/*
- * Periodic interval timer interrupt handler
- */
-#define Clock_driver_support_at_tick()             \
-    do {                                           \
-        MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;         \
-    } while (0)                                    \
+static void mcf5329_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &mcf5329_tc,
+    mcf5329_tc_get,
+    mcf5329_tc_at_tick
+  );
+}
 
 /*
  * Attach clock interrupt handler
diff --git a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
index 46e045c..1489d7e 100644
--- a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
@@ -17,6 +17,17 @@
 #include <mcf5282/mcf5282.h>
 
 /*
+ * CPU load counters
+ * Place in static RAM so updates don't hit the SDRAM
+ */
+#define IDLE_COUNTER    __SRAMBASE.idle_counter
+#define FILTERED_IDLE   __SRAMBASE.filtered_idle
+#define MAX_IDLE_COUNT  __SRAMBASE.max_idle_count
+#define PITC_PER_TICK   __SRAMBASE.pitc_per_tick
+#define NSEC_PER_PITC   __SRAMBASE.nsec_per_pitc
+#define FILTER_SHIFT    6
+
+/*
  * Use INTC0 base
  */
 #define CLOCK_VECTOR (64+58)
@@ -42,34 +53,24 @@ static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void uC5282_tc_tick(void)
+static void uC5282_tc_at_tick(rtems_timecounter_simple *tc)
 {
-  rtems_timecounter_simple_downcounter_tick(&uC5282_tc, uC5282_tc_get);
+  unsigned idle = IDLE_COUNTER;
+  IDLE_COUNTER = 0;
+  if (idle > MAX_IDLE_COUNT)
+    MAX_IDLE_COUNT = idle;
+  FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);
+  MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;
 }
 
-/*
- * CPU load counters
- * Place in static RAM so updates don't hit the SDRAM
- */
-#define IDLE_COUNTER    __SRAMBASE.idle_counter
-#define FILTERED_IDLE   __SRAMBASE.filtered_idle
-#define MAX_IDLE_COUNT  __SRAMBASE.max_idle_count
-#define PITC_PER_TICK   __SRAMBASE.pitc_per_tick
-#define NSEC_PER_PITC   __SRAMBASE.nsec_per_pitc
-#define FILTER_SHIFT    6
-
-/*
- * Periodic interval timer interrupt handler
- */
-#define Clock_driver_support_at_tick()                                       \
-    do {                                                                     \
-        unsigned idle = IDLE_COUNTER;                                        \
-        IDLE_COUNTER = 0;                                                    \
-        if (idle > MAX_IDLE_COUNT)                                           \
-            MAX_IDLE_COUNT = idle;                                           \
-        FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);\
-        MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;                           \
-    } while (0)
+static void uC5282_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &uC5282_tc,
+    uC5282_tc_get,
+    uC5282_tc_at_tick
+  );
+}
 
 /*
  * Attach clock interrupt handler
diff --git a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
index 4de9a52..c0b8905 100644
--- a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
+++ b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
@@ -55,18 +55,22 @@ static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void mpc55xx_tc_tick(void)
-{
-  rtems_timecounter_simple_upcounter_tick(&mpc55xx_tc, mpc55xx_tc_get);
-}
-
-static void mpc55xx_clock_at_tick(void)
+static void mpc55xx_tc_at_tick(rtems_timecounter_simple *tc)
 {
   union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
   csr.B.FLAG = 1;
   EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R;
 }
 
+static void mpc55xx_tc_tick(void)
+{
+  rtems_timecounter_simple_upcounter_tick(
+    &mpc55xx_tc,
+    mpc55xx_tc_get,
+    mpc55xx_tc_at_tick
+  );
+}
+
 static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -174,12 +178,7 @@ static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
   );
 }
 
-static void mpc55xx_tc_tick(void)
-{
-  rtems_timecounter_simple_downcounter_tick(&mpc55xx_tc, mpc55xx_tc_get);
-}
-
-static void mpc55xx_clock_at_tick(void)
+static void mpc55xx_tc_at_tick(rtems_timecounter_simple *tc)
 {
   volatile PIT_RTI_CHANNEL_tag *channel =
     &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
@@ -188,6 +187,15 @@ static void mpc55xx_clock_at_tick(void)
   channel->TFLG.R = tflg.R;
 }
 
+static void mpc55xx_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &mpc55xx_tc,
+    mpc55xx_tc_get,
+    mpc55xx_tc_at_tick
+  );
+}
+
 static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -238,8 +246,6 @@ static void mpc55xx_clock_cleanup(void)
 #endif
 
 #define Clock_driver_timecounter_tick() mpc55xx_tc_tick()
-#define Clock_driver_support_at_tick() \
-  mpc55xx_clock_at_tick()
 #define Clock_driver_support_initialize_hardware() \
   mpc55xx_clock_initialize()
 #define Clock_driver_support_install_isr(isr, old_isr) \
diff --git a/c/src/lib/libbsp/shared/clockdrv_shell.h b/c/src/lib/libbsp/shared/clockdrv_shell.h
index d546fb8..96b962f 100644
--- a/c/src/lib/libbsp/shared/clockdrv_shell.h
+++ b/c/src/lib/libbsp/shared/clockdrv_shell.h
@@ -44,6 +44,13 @@
   #define Clock_driver_support_find_timer()
 #endif
 
+/**
+ * @brief Do nothing by default.
+ */
+#ifndef Clock_driver_support_at_tick
+  #define Clock_driver_support_at_tick()
+#endif
+
 /*
  * A specialized clock driver may use for example rtems_timecounter_tick_simple()
  * instead of the default.
@@ -108,7 +115,14 @@ rtems_isr Clock_isr(
           && _Thread_Executing->Start.entry_point
             == (Thread_Entry) rtems_configuration_get_idle_task()
       ) {
-        _Timecounter_Tick_simple(interval, (*tc->tc_get_timecount)(tc));
+        ISR_lock_Context lock_context;
+
+        _Timecounter_Acquire(&lock_context);
+        _Timecounter_Tick_simple(
+          interval,
+          (*tc->tc_get_timecount)(tc),
+          &lock_context
+        );
       }
 
       Clock_driver_support_at_tick();
diff --git a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
index 46f99a5..f2d493e 100644
--- a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
@@ -36,8 +36,6 @@
  */
 #define CLOCK_VECTOR ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK )
 
-#define Clock_driver_support_at_tick()
-
 #define Clock_driver_support_install_isr( _new, _old ) \
   do { \
     _old = set_vector( _new, CLOCK_VECTOR, 1 ); \
@@ -66,11 +64,17 @@ static uint32_t erc32_tc_get_timecount( struct timecounter *tc )
   );
 }
 
+static void erc32_tc_at_tick( rtems_timecounter_simple *tc )
+{
+  /* Nothing to do */
+}
+
 static void erc32_tc_tick( void )
 {
   rtems_timecounter_simple_downcounter_tick(
     &erc32_tc,
-    erc32_tc_get
+    erc32_tc_get,
+    erc32_tc_at_tick
   );
 }
 
diff --git a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
index 3dd68e0..6c2cf98 100644
--- a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
@@ -51,9 +51,18 @@ static uint32_t leon2_tc_get_timecount( struct timecounter *tc )
   );
 }
 
+static void leon2_tc_at_tick( rtems_timecounter_simple *tc )
+{
+  /* Nothing to do */
+}
+
 static void leon2_tc_tick( void )
 {
-  rtems_timecounter_simple_downcounter_tick( &leon2_tc, leon2_tc_get );
+  rtems_timecounter_simple_downcounter_tick(
+    &leon2_tc,
+    leon2_tc_get,
+    leon2_tc_at_tick
+  );
 }
 
 /*
@@ -62,8 +71,6 @@ static void leon2_tc_tick( void )
 
 #define CLOCK_VECTOR LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 )
 
-#define Clock_driver_support_at_tick()
-
 #define Clock_driver_support_install_isr( _new, _old ) \
   do { \
     _old = set_vector( _new, CLOCK_VECTOR, 1 ); \
diff --git a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
index b82b457..5d645dc 100644
--- a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
@@ -69,15 +69,6 @@ static uint32_t leon3_tc_get_timecount_irqmp(struct timecounter *tc)
   return LEON3_IrqCtrl_Regs->timestamp[0].counter;
 }
 
-static void leon3_tc_tick(void)
-{
-  if (leon3_tc_use_irqmp) {
-    rtems_timecounter_tick();
-  } else {
-    rtems_timecounter_simple_downcounter_tick(&leon3_tc, leon3_tc_get);
-  }
-}
-
 static void leon3_clock_profiling_interrupt_delay(void)
 {
 #ifdef RTEMS_PROFILING
@@ -111,10 +102,24 @@ static void leon3_clock_profiling_interrupt_delay(void)
 #endif
 }
 
-#define Clock_driver_support_at_tick() \
-  do { \
-    leon3_clock_profiling_interrupt_delay(); \
-  } while (0)
+static void leon3_tc_at_tick( rtems_timecounter_simple *tc )
+{
+  leon3_clock_profiling_interrupt_delay();
+}
+
+static void leon3_tc_tick(void)
+{
+  if (leon3_tc_use_irqmp) {
+    leon3_clock_profiling_interrupt_delay();
+    rtems_timecounter_tick();
+  } else {
+    rtems_timecounter_simple_downcounter_tick(
+      &leon3_tc,
+      leon3_tc_get,
+      leon3_tc_at_tick
+    );
+  }
+}
 
 #define Adjust_clkirq_for_node() do { clkirq += LEON3_CLOCK_INDEX; } while(0)
 
diff --git a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c b/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
index b29f140..58e95d1 100644
--- a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
+++ b/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
@@ -29,7 +29,6 @@
 #undef CLOCK_DRIVER_ISRS_PER_TICK
 #undef CLOCK_DRIVER_USE_FAST_IDLE
 */
-#define Clock_driver_support_at_tick()
 
 /*
  *  Number of Clock ticks since initialization
@@ -87,11 +86,17 @@ static uint32_t tlib_tc_get_timecount(struct timecounter *tc)
   );
 }
 
+static void tlib_tc_at_tick(rtems_timecounter_simple *tc)
+{
+  /* Nothing to do? */
+}
+
 static void tlib_tc_tick(void)
 {
   rtems_timecounter_simple_downcounter_tick(
     &tlib_tc,
-    tlib_tc_get
+    tlib_tc_get,
+    tlib_tc_at_tick
   );
 }
 
@@ -130,16 +135,10 @@ void Clock_isr(void *arg_unused)
   } while ( _Thread_Executing == _Thread_Idle &&
           _Thread_Heir == _Thread_Executing);
 
-  Clock_driver_support_at_tick();
   return;
 
 #else
 
-  /*
-   * Add custom handling at every tick from bsp.h
-   */
-  Clock_driver_support_at_tick();
-
 #ifdef CLOCK_DRIVER_ISRS_PER_TICK
   /*
    *  The driver is multiple ISRs per clock tick.
diff --git a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
index 4887d2a..463125b 100644
--- a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
+++ b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
@@ -45,9 +45,26 @@ static uint32_t lpc22xx_tc_get_timecount(struct timecounter *tc)
   );
 }
 
+/**
+ * When we get the clock interrupt
+ *    - clear the interrupt bit?
+ *    - restart the timer?
+ */
+static void lpc22xx_tc_at_tick(rtems_timecounter_simple *tc)
+{
+  if (!(T0IR & 0x01))
+    return;
+  T0IR = 0x01;
+  VICVectAddr = 0x00;
+}
+
 static void lpc22xx_tc_tick(void)
 {
-  rtems_timecounter_simple_upcounter_tick(&lpc22xx_tc, lpc22xx_tc_get);
+  rtems_timecounter_simple_upcounter_tick(
+    &lpc22xx_tc,
+    lpc22xx_tc_get,
+    lpc22xx_tc_at_tick
+  );
 }
 
 /* Replace the first value with the clock's interrupt name. */
@@ -63,19 +80,6 @@ rtems_irq_connect_data clock_isr_data = {
 /* use the /shared/clockdrv_shell.h code template */
 
 /**
- * When we get the clock interrupt
- *    - clear the interrupt bit?
- *    - restart the timer?
- */
-#define Clock_driver_support_at_tick() \
- do {                                  \
-   if (!(T0IR & 0x01))                 \
-     return;                           \
-   T0IR = 0x01;                        \
-   VICVectAddr = 0x00;                 \
- } while(0)
-
-/**
  * Installs the clock ISR. You shouldn't need to change this.
  */
 #define Clock_driver_support_install_isr( _new, _old ) \
diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c
index e2cd35f..a6bf26d 100644
--- a/cpukit/rtems/src/clocktick.c
+++ b/cpukit/rtems/src/clocktick.c
@@ -23,9 +23,13 @@
 
 rtems_status_code rtems_clock_tick( void )
 {
+  ISR_lock_Context lock_context;
+
+  _Timecounter_Acquire( &lock_context );
   _Timecounter_Tick_simple(
     rtems_configuration_get_microseconds_per_tick(),
-    0
+    0,
+    &lock_context
   );
 
   return RTEMS_SUCCESSFUL;
diff --git a/cpukit/sapi/include/rtems/timecounter.h b/cpukit/sapi/include/rtems/timecounter.h
index 04bc534..db0a7ee 100644
--- a/cpukit/sapi/include/rtems/timecounter.h
+++ b/cpukit/sapi/include/rtems/timecounter.h
@@ -94,6 +94,13 @@ typedef struct {
 } rtems_timecounter_simple;
 
 /**
+ * @brief At tick handling done under protection of the timecounter lock.
+ */
+typedef void rtems_timecounter_simple_at_tick(
+  rtems_timecounter_simple *tc
+);
+
+/**
  * @brief Returns the current value of a simple timecounter.
  */
 typedef uint32_t rtems_timecounter_simple_get(
@@ -199,20 +206,28 @@ RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_scale(
  *
  * @param[in] tc The simple timecounter.
  * @param[in] get The method to get the value of the simple timecounter.
+ * @param[in] at_tick The method to perform work under timecounter lock
+ * protection at this tick, e.g. clear a pending flag.
  */
 RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick(
-  rtems_timecounter_simple     *tc,
-  rtems_timecounter_simple_get  get
+  rtems_timecounter_simple         *tc,
+  rtems_timecounter_simple_get      get,
+  rtems_timecounter_simple_at_tick  at_tick
 )
 {
+  ISR_lock_Context lock_context;
   uint32_t current;
 
+  _Timecounter_Acquire( &lock_context );
+
+  ( *at_tick )( tc );
+
   current = rtems_timecounter_simple_scale(
     tc,
     tc->real_interval - ( *get )( tc )
   );
 
-  _Timecounter_Tick_simple( tc->binary_interval, current );
+  _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context );
 }
 
 /**
@@ -220,17 +235,25 @@ RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick(
  *
  * @param[in] tc The simple timecounter.
  * @param[in] get The method to get the value of the simple timecounter.
+ * @param[in] at_tick The method to perform work under timecounter lock
+ * protection at this tick, e.g. clear a pending flag.
  */
 RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_upcounter_tick(
-  rtems_timecounter_simple     *tc,
-  rtems_timecounter_simple_get  get
+  rtems_timecounter_simple         *tc,
+  rtems_timecounter_simple_get      get,
+  rtems_timecounter_simple_at_tick  at_tick
 )
 {
+  ISR_lock_Context lock_context;
   uint32_t current;
 
+  _Timecounter_Acquire( &lock_context );
+
+  ( *at_tick )( tc );
+
   current = rtems_timecounter_simple_scale( tc, ( *get )( tc ) );
 
-  _Timecounter_Tick_simple( tc->binary_interval, current );
+  _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context );
 }
 
 /**
diff --git a/cpukit/score/include/rtems/score/timecounter.h b/cpukit/score/include/rtems/score/timecounter.h
index 0d17cc7..33de269 100644
--- a/cpukit/score/include/rtems/score/timecounter.h
+++ b/cpukit/score/include/rtems/score/timecounter.h
@@ -26,6 +26,8 @@
 #include <sys/time.h>
 #include <sys/timetc.h>
 
+#include <rtems/score/isrlock.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -161,6 +163,21 @@ void _Timecounter_Install( struct timecounter *tc );
 void _Timecounter_Tick( void );
 
 /**
+ * @brief Lock to protect the timecounter mechanic.
+ */
+ISR_LOCK_DECLARE( extern, _Timecounter_Lock )
+
+/**
+ * @brief Acquires the timecounter lock.
+ *
+ * @param[in] lock_context The lock context.
+ *
+ * See _Timecounter_Tick_simple().
+ */
+#define _Timecounter_Acquire( lock_context ) \
+  _ISR_lock_ISR_disable_and_acquire( &_Timecounter_Lock, lock_context )
+
+/**
  * @brief Performs a simple timecounter tick.
  *
  * This is a special purpose tick function for simple timecounter to support
@@ -169,8 +186,14 @@ void _Timecounter_Tick( void );
  * @param[in] delta The time in timecounter ticks elapsed since the last call
  * to _Timecounter_Tick_simple().
  * @param[in] offset The current value of the timecounter.
- */
-void _Timecounter_Tick_simple( uint32_t delta, uint32_t offset );
+ * @param[in] lock_context The lock context of the corresponding
+ * _Timecounter_Acquire().
+ */
+void _Timecounter_Tick_simple(
+  uint32_t delta,
+  uint32_t offset,
+  ISR_lock_Context *lock_context
+);
 
 /**
  * @brief The wall clock time in seconds.
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index f6a1136..4257533 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -64,7 +64,9 @@ __FBSDID("$FreeBSD r284178 2015-06-09T11:49:56Z$");
 #ifdef __rtems__
 #include <limits.h>
 #include <rtems.h>
-ISR_LOCK_DEFINE(static, _Timecounter_Lock, "Timecounter");
+ISR_LOCK_DEFINE(, _Timecounter_Lock, "Timecounter")
+#define _Timecounter_Release(lock_context) \
+  _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, lock_context)
 #define hz rtems_clock_get_ticks_per_second()
 #define printf(...)
 #define log(...)
@@ -1383,7 +1385,7 @@ tc_windup(void)
 #ifdef __rtems__
 	ISR_lock_Context lock_context;
 
-	_ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context);
+	_Timecounter_Acquire(&lock_context);
 #endif /* __rtems__ */
 
 	/*
@@ -1538,7 +1540,7 @@ tc_windup(void)
 	timekeep_push_vdso();
 #endif /* __rtems__ */
 #ifdef __rtems__
-	_ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context);
+	_Timecounter_Release(&lock_context);
 #endif /* __rtems__ */
 }
 
@@ -1963,14 +1965,12 @@ _Timecounter_Tick(void)
 }
 #ifdef __rtems__
 void
-_Timecounter_Tick_simple(uint32_t delta, uint32_t offset)
+_Timecounter_Tick_simple(uint32_t delta, uint32_t offset,
+    ISR_lock_Context *lock_context)
 {
 	struct bintime bt;
 	struct timehands *th;
 	uint32_t ogen;
-	ISR_lock_Context lock_context;
-
-	_ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context);
 
 	th = timehands;
 	ogen = th->th_generation;
@@ -1997,7 +1997,7 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset)
 	time_second = th->th_microtime.tv_sec;
 	time_uptime = th->th_offset.sec;
 
-	_ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context);
+	_Timecounter_Release(lock_context);
 
 	_Watchdog_Tick();
 }
diff --git a/doc/bsp_howto/clock.t b/doc/bsp_howto/clock.t
index f58b898..2891bb2 100644
--- a/doc/bsp_howto/clock.t
+++ b/doc/bsp_howto/clock.t
@@ -89,6 +89,13 @@ static uint32_t some_tc_get( rtems_timecounter_simple *tc )
   return some.counter;
 @}
 
+static void some_tc_at_tick( rtems_timecounter_simple *tc )
+@{
+  /*
+   * Do work necessary at the clock tick interrupt, e.g. clear a pending flag.
+   */
+@}
+
 static bool some_tc_is_pending( rtems_timecounter_simple *tc )
 @{
   return some.is_pending;
@@ -105,7 +112,11 @@ static uint32_t some_tc_get_timecount( struct timecounter *tc )
 
 static void some_tc_tick( void )
 @{
-  rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get );
+  rtems_timecounter_simple_downcounter_tick(
+    &some_tc,
+    some_tc_get,
+    some_tc_at_tick
+  );
 @}
 
 static void some_support_initialize_hardware( void )




More information about the vc mailing list