[PATCH 4/4] bsps: Convert clock driver to use timecounters
Alexander Krutwig
alexander.krutwig at embedded-brains.de
Wed Apr 8 12:44:16 UTC 2015
Example using the ERC32. After review all BSPs will get converted.
---
c/src/lib/libbsp/shared/clockdrv_shell.h | 30 +++++++++++-----
c/src/lib/libbsp/sparc/erc32/clock/ckinit.c | 54 +++++++++++++++++++++++------
2 files changed, 65 insertions(+), 19 deletions(-)
diff --git a/c/src/lib/libbsp/shared/clockdrv_shell.h b/c/src/lib/libbsp/shared/clockdrv_shell.h
index 5dbea13..63ed3fa 100644
--- a/c/src/lib/libbsp/shared/clockdrv_shell.h
+++ b/c/src/lib/libbsp/shared/clockdrv_shell.h
@@ -20,6 +20,10 @@
#include <bsp.h>
#include <rtems/clockdrv.h>
+#ifdef Clock_driver_nanoseconds_since_last_tick
+#error "Update driver to use the timecounter instead of nanoseconds extension"
+#endif
+
/**
* @defgroup bsp_clock Clock Support
*
@@ -39,6 +43,14 @@
#define Clock_driver_support_find_timer()
#endif
+/*
+ * A specialized clock driver may use for example _Timecounter_Tick_simple()
+ * instead of the default.
+ */
+#ifndef Clock_driver_timecounter_tick
+ Clock_driver_timecounter_tick() _Timecounter_Tick()
+#endif
+
/**
* @brief ISRs until next clock tick
*/
@@ -53,6 +65,12 @@ volatile uint32_t Clock_driver_ticks;
void Clock_exit( void );
+static void Clock_tick( void )
+{
+ Clock_driver_timecounter_tick();
+ rtems_clock_tick();
+}
+
/**
* @brief Clock_isr
*
@@ -79,7 +97,7 @@ rtems_isr Clock_isr(
#if CLOCK_DRIVER_USE_FAST_IDLE
do {
- rtems_clock_tick();
+ Clock_tick();
} while (
_Thread_Heir == _Thread_Executing
&& _Thread_Executing->Start.entry_point
@@ -101,7 +119,7 @@ rtems_isr Clock_isr(
* The driver is multiple ISRs per clock tick.
*/
if ( !Clock_driver_isrs ) {
- rtems_clock_tick();
+ Clock_tick();
Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
}
@@ -110,7 +128,7 @@ rtems_isr Clock_isr(
/*
* The driver is one ISR per clock tick.
*/
- rtems_clock_tick();
+ Clock_tick();
#endif
#endif
}
@@ -160,12 +178,6 @@ rtems_device_driver Clock_initialize(
(void) Old_ticker;
Clock_driver_support_install_isr( Clock_isr, Old_ticker );
- #if defined(Clock_driver_nanoseconds_since_last_tick)
- rtems_clock_set_nanoseconds_extension(
- Clock_driver_nanoseconds_since_last_tick
- );
- #endif
-
/*
* Now initialize the hardware that is the source of the tick ISR.
*/
diff --git a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
index 2afe770..721643b 100644
--- a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
@@ -25,6 +25,7 @@
#include <bsp.h>
#include <bspopts.h>
#include <rtems/counter.h>
+#include <rtems/timecounter.h>
#if SIMSPARC_FAST_IDLE==1
#define CLOCK_DRIVER_USE_FAST_IDLE 1
@@ -44,25 +45,33 @@
extern int CLOCK_SPEED;
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
+static struct timecounter erc32_tc;
+
+static uint64_t erc32_tc_scaler;
+
+static uint32_t erc32_tc_interval;
+
+static uint32_t erc32_tc_current(void)
+{
+ return (ERC32_MEC.Real_Time_Clock_Counter * erc32_tc_scaler) >> 32;
+}
+
+static u_int erc32_get_timecount(struct timecounter *tc)
{
uint32_t clicks;
- uint32_t usecs;
+ uint32_t interval;
- clicks = ERC32_MEC.Real_Time_Clock_Counter;
+ interval = erc32_tc_interval;
+ clicks = erc32_tc_current();
if ( ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK ) ) {
- clicks = ERC32_MEC.Real_Time_Clock_Counter;
- usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks);
+ clicks = erc32_tc_current();
+ return (2 * interval - clicks);
} else {
- usecs = (rtems_configuration_get_microseconds_per_tick() - clicks);
+ return (interval - clicks);
}
- return usecs * 1000;
}
-#define Clock_driver_nanoseconds_since_last_tick \
- bsp_clock_nanoseconds_since_last_tick
-
static CPU_Counter_ticks erc32_counter_difference(
CPU_Counter_ticks second,
CPU_Counter_ticks first
@@ -75,6 +84,7 @@ static CPU_Counter_ticks erc32_counter_difference(
#define Clock_driver_support_initialize_hardware() \
do { \
+ uint32_t mask; \
/* approximately 1 us per countdown */ \
ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1; \
ERC32_MEC.Real_Time_Clock_Counter = \
@@ -89,7 +99,18 @@ static CPU_Counter_ticks erc32_counter_difference(
ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \
ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \
ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO \
+ ); \
+ rtems_timecounter_get_binary_scaler_and_mask( \
+ rtems_configuration_get_microseconds_per_tick(), \
+ &erc32_tc_scaler, \
+ &mask \
); \
+ erc32_tc_interval = (mask + 1) / 2; \
+ erc32_tc.tc_get_timecount = erc32_get_timecount; \
+ erc32_tc.tc_counter_mask = mask; \
+ erc32_tc.tc_frequency = (1000000 * erc32_tc_scaler) >> 32; \
+ erc32_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; \
+ rtems_timecounter_install(&erc32_tc); \
_SPARC_Counter_initialize( \
&ERC32_MEC.Real_Time_Clock_Counter, \
erc32_counter_difference \
@@ -97,6 +118,19 @@ static CPU_Counter_ticks erc32_counter_difference(
rtems_counter_initialize_converter(1000000); \
} while (0)
+static void erc32_tc_tick(void)
+{
+ uint32_t clicks;
+ uint32_t interval;
+
+ interval = erc32_tc_interval;
+ clicks = interval - erc32_tc_current();
+
+ rtems_timecounter_tick_simple(interval + clicks, clicks);
+}
+
+#define Clock_driver_timecounter_tick() erc32_tc_tick()
+
#define Clock_driver_support_shutdown_hardware() \
do { \
ERC32_Mask_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK ); \
--
1.8.4.5
More information about the devel
mailing list