Simplify _CPU_Counter_difference()

In order to simplify the use of CPU counter values it is beneficial to
have monotonic increasing values within the range of the CPU counter
ticks data type, e.g. 32-bit unsigned integer.  This eases the use of
CPU counter timestamps in external tools which do not know the details
of the CPU counter hardware.  The CPU counter is the fastest way to get
a time on an RTEMS system.

Such a CPU counter may be also used as the timecounter.  Use it on SPARC
for this purpose to simplify the clock drivers.

Update #3456.
This commit is contained in:
Sebastian Huber
2018-05-03 13:03:27 +02:00
parent ef23838543
commit 0a1f5df98e
15 changed files with 337 additions and 352 deletions

View File

@@ -24,42 +24,73 @@
#include <bsp.h>
#include <bspopts.h>
#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
#include <rtems/score/sparcimpl.h>
static rtems_timecounter_simple leon2_tc;
extern int CLOCK_SPEED;
static uint32_t leon2_tc_get( rtems_timecounter_simple *tc )
#define LEON2_TIMER_1_FREQUENCY 1000000
static struct timecounter leon2_tc;
static void leon2_clock_init( void )
{
return LEON_REG.Timer_Counter_1;
struct timecounter *tc;
tc = &leon2_tc;
tc->tc_get_timecount = _SPARC_Get_timecount_clock;
tc->tc_counter_mask = 0xffffffff;
tc->tc_frequency = LEON2_TIMER_1_FREQUENCY;
tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install(tc);
}
static bool leon2_tc_is_pending( rtems_timecounter_simple *tc )
static void leon2_clock_at_tick( void )
{
return LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 );
SPARC_Counter *counter;
rtems_interrupt_level level;
counter = &_SPARC_Counter_mutable;
rtems_interrupt_local_disable(level);
LEON_Clear_interrupt( LEON_INTERRUPT_TIMER1 );
counter->accumulated += counter->interval;
rtems_interrupt_local_enable(level);
}
static uint32_t leon2_tc_get_timecount( struct timecounter *tc )
static void leon2_clock_initialize_early( void )
{
return rtems_timecounter_simple_downcounter_get(
tc,
leon2_tc_get,
leon2_tc_is_pending
SPARC_Counter *counter;
LEON_REG.Timer_Reload_1 =
rtems_configuration_get_microseconds_per_tick() - 1;
LEON_REG.Timer_Control_1 = (
LEON_REG_TIMER_COUNTER_ENABLE_COUNTING |
LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO |
LEON_REG_TIMER_COUNTER_LOAD_COUNTER
);
counter = &_SPARC_Counter_mutable;
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
counter->read = _SPARC_Counter_read_clock;
counter->counter_register = &LEON_REG.Timer_Counter_1;
counter->pending_register = &LEON_REG.Interrupt_Pending;
counter->pending_mask = UINT32_C(1) << LEON_INTERRUPT_TIMER1;
counter->accumulated = rtems_configuration_get_microseconds_per_tick();
counter->interval = rtems_configuration_get_microseconds_per_tick();
}
static void leon2_tc_at_tick( rtems_timecounter_simple *tc )
{
/* Nothing to do */
}
RTEMS_SYSINIT_ITEM(
leon2_clock_initialize_early,
RTEMS_SYSINIT_CPU_COUNTER,
RTEMS_SYSINIT_ORDER_FIRST
);
static void leon2_tc_tick( void )
uint32_t _CPU_Counter_frequency(void)
{
rtems_timecounter_simple_downcounter_tick(
&leon2_tc,
leon2_tc_get,
leon2_tc_at_tick
);
return LEON2_TIMER_1_FREQUENCY;
}
/*
@@ -71,27 +102,9 @@ static void leon2_tc_tick( void )
#define Clock_driver_support_install_isr( _new ) \
set_vector( _new, CLOCK_VECTOR, 1 )
extern int CLOCK_SPEED;
#define Clock_driver_support_at_tick() leon2_clock_at_tick()
#define Clock_driver_support_initialize_hardware() \
do { \
LEON_REG.Timer_Reload_1 = \
rtems_configuration_get_microseconds_per_tick() - 1; \
\
LEON_REG.Timer_Control_1 = ( \
LEON_REG_TIMER_COUNTER_ENABLE_COUNTING | \
LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO | \
LEON_REG_TIMER_COUNTER_LOAD_COUNTER \
); \
rtems_timecounter_simple_install( \
&leon2_tc, \
1000000, \
rtems_configuration_get_microseconds_per_tick(), \
leon2_tc_get_timecount \
); \
} while (0)
#define Clock_driver_timecounter_tick() leon2_tc_tick()
#define Clock_driver_support_initialize_hardware() leon2_clock_init()
#include "../../../shared/dev/clock/clockimpl.h"