bsps: Move benchmark timer to bsps

This patch is a part of the BSP source reorganization.

Update #3285.
This commit is contained in:
Sebastian Huber
2018-04-20 12:08:42 +02:00
parent 9964895866
commit e0dd8a5ad8
86 changed files with 49 additions and 49 deletions

View File

@@ -28,7 +28,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterread.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterdiff.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/csb336/clock/clockdrv.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb336/btimer/btimer.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb336/console/uart.c
# IRQ

View File

@@ -1,93 +0,0 @@
/**
* @file
* @brief Cogent CSB336 Timer driver
*
* This uses timer 2 for timing measurments.
*/
/*
* Copyright (c) 2004 Cogent Computer Systems
* Written by Jay Monkman <jtm@lopingdog.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <mc9328mxl.h>
uint32_t g_start;
uint32_t g_freq;
bool benchmark_timer_find_average_overhead;
/*
* Set up Timer 1
*/
void benchmark_timer_initialize( void )
{
MC9328MXL_TMR2_TCTL = (MC9328MXL_TMR_TCTL_CLKSRC_PCLK1 |
MC9328MXL_TMR_TCTL_FRR |
MC9328MXL_TMR_TCTL_TEN);
/* set prescaler to 1 (register value + 1) */ \
MC9328MXL_TMR2_TPRER = 0;
/* get freq of counter in KHz */
g_freq = get_perclk1_freq() / 1000;
g_start = MC9328MXL_TMR2_TCN;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t t;
unsigned long long total;
t = MC9328MXL_TMR2_TCN;
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = (t - g_start);
/* convert to nanoseconds */
total = (total * 1000)/ g_freq;
if ( benchmark_timer_find_average_overhead == 1 ) {
return (int) total;
} else if ( total < LEAST_VALID ) {
return 0;
}
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -38,7 +38,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounter
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterdiff.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/start/pmc.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/csb337/clock/clock.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/btimer/btimer.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console-control.c

View File

@@ -1,91 +0,0 @@
/**
* @file
* @brief Cogent CSB337 Timer driver
*
* This uses timer 0 for timing measurments.
*/
/*
* Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <rtems.h>
#include <rtems/btimer.h>
#include <at91rm9200.h>
#include <at91rm9200_pmc.h>
uint16_t tstart;
bool benchmark_timer_find_average_overhead;
uint32_t tick_time;
/*
* Set up TC0 -
* timer_clock2 (MCK/8)
* capture mode - this shouldn't matter
*/
void benchmark_timer_initialize( void )
{
uint32_t tmr_freq;
/* since we are using timer_clock2, divide mck by 8 */
tmr_freq = at91rm9200_get_mck() / 8;
TC_TC0_REG(TC_CMR) = TC_CMR_TCCLKS(1); /* timer_clock2 */
TC_TC0_REG(TC_CCR) = (TC_CCR_CLKEN /* enable the counter */
| TC_CCR_SWTRG); /* start it up */
/* tick time in nanoseconds */
tick_time = 1000000000/tmr_freq;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint16_t t;
uint32_t total;
t = TC_TC0_REG(TC_CV);
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = t * tick_time;
if ( benchmark_timer_find_average_overhead == 1 )
return total; /* in nanosecond units */
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console-select.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/edb7312/console/uart.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/edb7312/btimer/btimer.c
# irq
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c

View File

@@ -1,80 +0,0 @@
/*
* Cirrus EP7312 Timer driver
*
* Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Notes:
* This file manages the benchmark timer used by the RTEMS Timing Test
* Suite. Each measured time period is demarcated by calls to
* benchmark_timer_initialize() and benchmark_timer_read(). benchmark_timer_read() usually returns
* the number of microseconds since benchmark_timer_initialize() exitted.
*
* It is important that the timer start/stop overhead be determined
* when porting or modifying this code.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <ep7312.h>
uint16_t tstart;
bool benchmark_timer_find_average_overhead;
void benchmark_timer_initialize( void )
{
*EP7312_SYSCON1 |= EP7312_SYSCON1_TC2_512KHZ;
*EP7312_TC2D = 0xffff;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint16_t t;
uint32_t total;
t = *EP7312_TC2D;
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = (uint32_t)0x0000ffff - t; /* result is 1/512000 = ~2 uS */
total = (total * 1953) / 1000; /* convert to uS */
if ( benchmark_timer_find_average_overhead == true )
return total; /* in XXX microsecond units */
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -27,7 +27,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gumstix/start/memmap.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterread.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterdiff.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/gumstix/clock/clock.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gumstix/btimer/btimer.c
#console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c

View File

@@ -1,75 +0,0 @@
/**
* @file
* @brief PXA255 timer
*/
/*
* PXA255 timer by Yang Xi <hiyangxi@gmail.com>
* Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <rtems.h>
#include <rtems/btimer.h>
#include <pxa255.h>
uint32_t tstart;
static uint32_t tick_time;
bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false;
/*
* Use the timer count register to measure.
* The frequency of it is 3.4864MHZ
* The longest period we are able to capture is 4G/3.4864MHZ
*/
void benchmark_timer_initialize(void)
{
tick_time = XSCALE_OS_TIMER_TCR;
}
/*
* The following controls the behavior of Read_timer().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = XSCALE_OS_TIMER_TCR;
if(total>=tick_time)
total -= tick_time;
else
total += 0xffffffff - tick_time; /*Round up but not overflow*/
if ( benchmark_timer_find_average_overhead == true )
return total; /*Counter cycles*/
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -84,7 +84,7 @@ librtemsbsp_a_SOURCES += pwmout/pwmout.c
librtemsbsp_a_SOURCES += adc/adc.c
# Timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc176x/btimer/btimer.c
# Benchmark Timer
librtemsbsp_a_SOURCES += benchmark_timer/benchmark_timer.c

View File

@@ -1,407 +0,0 @@
/**
* @file timer.c
*
* @ingroup lpc176x
*
* @brief Timer controller for the mbed lpc1768 board.
*/
/*
* Copyright (c) 2014 Taller Technologies.
*
* @author Boretto Martin (martin.boretto@tallertechnologies.com)
* @author Diaz Marcos (marcos.diaz@tallertechnologies.com)
* @author Lenarduzzi Federico (federico.lenarduzzi@tallertechnologies.com)
* @author Daniel Chicco (daniel.chicco@tallertechnologies.com)
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <stdio.h>
#include <rtems/status-checks.h>
#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/io.h>
#include <bsp/timer.h>
/**
* @brief Represents all the timers.
*/
const lpc176x_timer timers[ LPC176X_TIMER_COUNT ] =
{
{
.device = (lpc176x_timer_device *) LPC176X_TMR0_BASE_ADDR,
.module = LPC176X_MODULE_TIMER_0,
.pinselcap = LPC176X_TIMER0_CAPTURE_PORTS,
.pinselemat = LPC176X_TIMER0_EMATCH_PORTS,
},
{
.device = (lpc176x_timer_device *) LPC176X_TMR1_BASE_ADDR,
.module = LPC176X_MODULE_TIMER_1,
.pinselcap = LPC176X_TIMER1_CAPTURE_PORTS,
.pinselemat = LPC176X_TIMER1_EMATCH_PORTS,
},
{
.device = (lpc176x_timer_device *) LPC176X_TMR2_BASE_ADDR,
.module = LPC176X_MODULE_TIMER_2,
.pinselcap = LPC176X_TIMER2_CAPTURE_PORTS,
.pinselemat = LPC176X_TIMER2_EMATCH_PORTS,
},
{
.device = (lpc176x_timer_device *) LPC176X_TMR3_BASE_ADDR,
.module = LPC176X_MODULE_TIMER_3,
.pinselcap = LPC176X_TIMER3_CAPTURE_PORTS,
.pinselemat = LPC176X_TIMER3_EMATCH_PORTS,
}
};
/**
* @brief Represents all the functions according to the timers.
*/
lpc176x_timer_functions functions_vector[ LPC176X_TIMER_COUNT ] =
{
{
.funct_vector = NULL
},
{
.funct_vector = NULL
},
{
.funct_vector = NULL
},
{
.funct_vector = NULL
}
};
/**
* @brief Calls the corresponding interrupt function and pass the timer
* as parameter.
*
* @param timer The specific device.
* @param interruptnumber Interrupt number.
*/
static inline void lpc176x_call_desired_isr(
const lpc176x_timer_number number,
const lpc176x_isr_function interruptfunction
)
{
if ( ( *functions_vector[ number ].funct_vector )[ interruptfunction ] !=
NULL ) {
( *functions_vector[ number ].funct_vector )[ interruptfunction ]( number );
}
/* else implies that the function vector points NULL. Also,
there is nothing to do. */
}
/**
* @brief Gets true if the selected interrupt is pending
*
* @param number: the number of the timer.
* @param interrupt: the interrupt we are checking for.
* @return TRUE if the interrupt is pending.
*/
static inline bool lpc176x_timer_interrupt_is_pending(
const lpc176x_timer_number tnumber,
const lpc176x_isr_function function
)
{
assert( ( tnumber < LPC176X_TIMER_COUNT )
&& ( function < LPC176X_ISR_FUNCTIONS_COUNT ) );
return ( timers[ tnumber ].device->IR &
LPC176X_TIMER_INTERRUPT_SOURCE_BIT( function ) );
}
/**
* @brief Resets interrupt status for the selected interrupt
*
* @param tnumber: the number of the timer
* @param interrupt: the interrupt we are resetting
*/
static inline void lpc176x_timer_reset_interrupt(
const lpc176x_timer_number tnumber,
const lpc176x_isr_function function
)
{
assert( ( tnumber < LPC176X_TIMER_COUNT )
&& ( function < LPC176X_ISR_FUNCTIONS_COUNT ) );
timers[ tnumber ].device->IR =
LPC176X_TIMER_INTERRUPT_SOURCE_BIT( function );
}
inline rtems_status_code lpc176x_timer_reset(
const lpc176x_timer_number tnumber )
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
timers[ tnumber ].device->TCR = LPC176X_TIMER_RESET;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_set_mode(
const lpc176x_timer_number tnumber,
const lpc176x_timer_mode mode
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
timers[ tnumber ].device->CTCR = mode;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_start(
const lpc176x_timer_number tnumber )
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
timers[ tnumber ].device->TCR = LPC176X_TIMER_START;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_is_started(
const lpc176x_timer_number tnumber,
bool *is_started
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
*is_started = ( timers[ tnumber ].device->TCR & LPC176X_TIMER_START ) ==
LPC176X_TIMER_START;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_set_resolution(
const lpc176x_timer_number tnumber,
const lpc176x_microseconds resolution
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
timers[ tnumber ].device->PR = ( LPC176X_CCLK /
LPC176X_TIMER_PRESCALER_DIVISOR ) *
resolution;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
rtems_status_code lpc176x_timer_match_config(
const lpc176x_timer_number tnumber,
const lpc176x_match_port match_port,
const lpc176x_match_function function,
const uint32_t match_value
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( ( tnumber < LPC176X_TIMER_COUNT )
&& ( match_port < LPC176X_EMATCH_PORTS_COUNT )
&& ( function < LPC176X_TIMER_MATCH_FUNCTION_COUNT ) ) {
timers[ tnumber ].device->MCR =
LPC176X_SET_MCR( timers[ tnumber ].device->MCR,
match_port, function );
timers[ tnumber ].device->MR[ match_port ] = match_value;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number, or a match port or a function
is invalid. Also, an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_capture_config(
const lpc176x_timer_number tnumber,
const lpc176x_capture_port capture_port,
const lpc176x_capture_function function
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( ( tnumber < LPC176X_TIMER_COUNT )
&& ( capture_port < LPC176X_CAPTURE_PORTS_COUNT )
&& ( function < LPC176X_TIMER_CAPTURE_FUNCTION_COUNT ) ) {
timers[ tnumber ].device->CCR =
LPC176X_SET_CCR( timers[ tnumber ].device->CCR,
capture_port, function );
lpc176x_pin_select( timers[ tnumber ].pinselcap[ capture_port ],
LPC176X_PIN_FUNCTION_11 );
}
/* else implies that the timer number or the capture port is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline rtems_status_code lpc176x_timer_external_match_config(
const lpc176x_timer_number number,
const lpc176x_match_port match_port,
const lpc176x_ext_match_function function
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( ( number < LPC176X_TIMER_COUNT )
&& ( match_port < LPC176X_EMATCH_PORTS_COUNT ) ) {
timers[ number ].device->EMR =
LPC176X_SET_EMR( timers[ number ].device->EMR,
match_port, function );
lpc176x_pin_select( timers[ number ].pinselemat[ match_port ],
LPC176X_PIN_FUNCTION_11 );
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number or the match port is invalid. Also,
an invalid number is returned. */
return status_code;
}
inline uint32_t lpc176x_timer_get_capvalue(
const lpc176x_timer_number number,
const lpc176x_capture_port capture_port
)
{
assert( ( number < LPC176X_TIMER_COUNT )
&& ( capture_port < LPC176X_CAPTURE_PORTS_COUNT ) );
return timers[ number ].device->CR[ capture_port ];
}
inline uint32_t lpc176x_timer_get_timer_value(
const lpc176x_timer_number tnumber )
{
assert( tnumber < LPC176X_TIMER_COUNT );
return timers[ tnumber ].device->TC;
}
inline rtems_status_code lpc176x_timer_set_timer_value(
const lpc176x_timer_number tnumber,
const uint32_t timer_value
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
timers[ tnumber ].device->TC = timer_value;
status_code = RTEMS_SUCCESSFUL;
}
/* else implies that the timer number is invalid. Also,
an invalid number is returned. */
return status_code;
}
void lpc176x_timer_isr( void *arg )
{
const lpc176x_timer_number tnumber = (lpc176x_timer_number) arg;
if ( tnumber < LPC176X_TIMER_COUNT ) {
lpc176x_isr_function i;
for ( i = 0; i < LPC176X_ISR_FUNCTIONS_COUNT; ++i ) {
if ( lpc176x_timer_interrupt_is_pending( tnumber, i ) ) {
lpc176x_call_desired_isr( tnumber, i );
lpc176x_timer_reset_interrupt( tnumber, i );
}
/* else implies that the current timer is not pending. Also,
there is nothing to do. */
}
}
/* else implies that the timer number is not valid. Also,
there is nothing to do. */
}
rtems_status_code lpc176x_timer_init( const lpc176x_timer_number tnumber )
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
if ( tnumber < LPC176X_TIMER_COUNT ) {
status_code = lpc176x_module_enable( timers[ tnumber ].module,
LPC176X_MODULE_PCLK_DEFAULT );
RTEMS_CHECK_SC( status_code, "Enabling the timer module." );
status_code = lpc176x_timer_reset( tnumber );
status_code = lpc176x_timer_set_mode( tnumber,
LPC176X_TIMER_MODE_TIMER );
status_code = lpc176x_timer_set_resolution( tnumber,
LPC176X_TIMER_DEFAULT_RESOLUTION );
timers[ tnumber ].device->MCR = LPC176X_TIMER_CLEAR_FUNCTION;
timers[ tnumber ].device->CCR = LPC176X_TIMER_CLEAR_FUNCTION;
timers[ tnumber ].device->EMR = LPC176X_TIMER_CLEAR_FUNCTION;
}
/* else implies that the timer number is not valid. Also,
an invalid number is returned. */
return status_code;
}
rtems_status_code lpc176x_timer_init_with_interrupt(
const lpc176x_timer_number tnumber,
const lpc176x_isr_funct_vector *const vector
)
{
rtems_status_code status_code = RTEMS_INVALID_NUMBER;
char isrname[ LPC176X_ISR_NAME_STRING_SIZE ];
snprintf( isrname, LPC176X_ISR_NAME_STRING_SIZE, "TimerIsr%d", tnumber );
if ( tnumber < LPC176X_TIMER_COUNT && vector != NULL ) {
functions_vector[ tnumber ].funct_vector = vector;
status_code = lpc176x_timer_init( tnumber );
status_code = rtems_interrupt_handler_install(
LPC176X_TIMER_VECTOR_NUMBER( tnumber ),
isrname,
RTEMS_INTERRUPT_UNIQUE,
lpc176x_timer_isr,
(void *) tnumber );
}
return status_code;
}

View File

@@ -27,7 +27,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterread.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterdiff.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/rtl22xx/btimer/btimer.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/rtl22xx/clock/clockdrv.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c

View File

@@ -1,48 +0,0 @@
#ifndef __LPC_TIMER_H
#define __LPC_TIMER_H
/*************************************************************************
*
* File name : Timer.h
*
**************************************************************************/
/* Timer Control register bit descriptions */
#define TCR_ENABLE_BIT 0
#define TCR_RESET_BIT 1
// The channel name which is used in matching, in fact they represent
// corresponding Match Register
#define CH_MAXNUM 4
#define CH0 0
#define CH1 1
#define CH2 2
#define CH3 3
// The channel name which is used in capturing, in fact they represent
// corresponding Capture Register
#define CPCH_MAXNUM 4
#define CPCH0 0
#define CPCH1 1
#define CPCH2 2
#define CPCH3 3
//The actions when matching
#define TimerAction_Interrupt 0x1
#define TimerAction_ResetTimer 0x2
#define TimerAction_StopTimer 0x4
//Interrupt source type
#define TIMERMR0Int 0x01
#define TIMERMR1Int 0x02
#define TIMERMR2Int 0x04
#define TIMERMR3Int 0x08
#define TIMERCR0Int 0x10
#define TIMERCR1Int 0x20
#define TIMERCR2Int 0x40
#define TIMERCR3Int 0x80
#define TIMERALLInt 0xFF
#endif //__LPC_Timer_H

View File

@@ -1,65 +0,0 @@
/**
* @file
* @brief RTL22xx board Timer driver
*
* This uses Timer1 for timing measurments.
*/
/*
* By Ray Xu <rayx.cn@gmail.com>, modify form Mc9328mxl RTEMS DSP
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <rtems.h>
#include <rtems/btimer.h>
#include <lpc22xx.h>
#include "lpc_timer.h"
uint32_t g_start;
uint32_t g_freq;
bool benchmark_timer_find_average_overhead;
/*
* Set up Timer 1
*/
void benchmark_timer_initialize( void )
{
g_freq = LPC22xx_Fpclk / 1000;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
return (T0TC/(LPC22xx_Fpclk/1000000));
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -27,7 +27,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterread.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterdiff.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/smdk2410/btimer/btimer.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/smdk2410/clock/clockdrv.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/arm/smdk2410/clock/support.c
# console

View File

@@ -1,100 +0,0 @@
/**
* @file
* @brief S3C2400 Timer driver
*
* This uses timer 1 for timing measurments.
*/
/*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <rtems.h>
#include <rtems/btimer.h>
#include <s3c24xx.h>
uint32_t g_start;
uint32_t g_freq;
bool benchmark_timer_find_average_overhead;
/*
* Set up Timer 1
*/
void benchmark_timer_initialize( void )
{
uint32_t cr;
/* stop TIMER1*/
cr=rTCON & 0xFFFFF0FF;
rTCON=(cr | (0x0 << 8));
/* set MUX for Timer1 to 1/2 */
cr=rTCFG1 & 0xFFFFFF0F;
rTCFG1=(cr | (0<<4));
/* input freq=PLCK/2 Mhz*/
g_freq = get_PCLK() / 2000;
rTCNTB1 = 0xFFFF;
/* start TIMER1 with manual reload */
cr=rTCON & 0xFFFFF0FF;
rTCON=(cr | (0x1 << 9));
rTCON=(cr | (0x1 << 8));
g_start = rTCNTO1;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t t;
unsigned long long total;
t = rTCNTO1;
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = (g_start - t);
/* convert to microseconds */
total = (total*1000) / g_freq;
if ( benchmark_timer_find_average_overhead == 1 ) {
return (int) total;
} else if ( total < LEAST_VALID ) {
return 0;
}
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -45,7 +45,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-defa
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/clock/clock-simidle.c
# Timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/epiphany/epiphany_sim/btimer/btimer.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c

View File

@@ -1,109 +0,0 @@
/*
* Copyright (c) 2015 University of York.
* Hesham ALMatary <hmka501@york.ac.uk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <rtems/score/epiphany-utility.h>
extern char bsp_start_vector_table_begin[];
bool benchmark_timer_find_average_overhead;
static void benchmark_timer1_interrupt_handler(void)
{
unsigned int val = 0xFFFFFFFF;
unsigned int event_type = 0x1;
/* Embed assembly code for setting timer1 */
__asm__ __volatile__ ("movts ctimer1, %[val] \t \n" :: [val] "r" (val));
__asm__ __volatile__ ("movfs r16, config; \t \n"
"mov r17, %%low(0xfffff0ff);\t \n"
"movt r17, %%high(0xffff0ff);\t \n"
"lsl r18, %[event_type], 0x8; \t \n"
"and r16, r16, r17; \t \n"
"orr r16, r16, r18; \t \n"
"movts config, r16; \t \n"
:: [event_type] "r" (event_type));
}
/* Start eCore tiemr 1 usef for profiling and timing analysis */
void benchmark_timer_initialize( void )
{
/* Install interrupt handler for timer 1 */
proc_ptr *table =
(proc_ptr *) bsp_start_vector_table_begin;
table[TIMER1] = benchmark_timer1_interrupt_handler;
benchmark_timer1_interrupt_handler();
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t timer_val = 0;
uint32_t total;
__asm__ __volatile__ ("movfs %[timer_val], ctimer1 \t \n"
:[timer_val] "=r" (timer_val):);
total = (0xFFFFFFFF - timer_val);
if ( benchmark_timer_find_average_overhead == true )
return total;
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -122,8 +122,8 @@ librtemsbsp_a_SOURCES += ../shared/irq/irq_asm.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/timerisr.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/btimer/timerisr.S
if HAS_IDE
# ide

View File

@@ -1,552 +0,0 @@
/*
* This file contains the PC386 timer package.
*
* Rosimildo daSilva -ConnectTel, Inc - Fixed infinite loop in the Calibration
* routine. I've seen this problems with faster machines ( pentiums ). Sometimes
* RTEMS just hangs at startup.
*
* Joel 9 May 2010: This is now seen sometimes on qemu.
*
* Modifications by:
* (C) Copyright 1997 -
* NavIST Group - Real-Time Distributed Systems and Industrial Automation
* http://pandora.ist.utl.pt
* Instituto Superior Tecnico * Lisboa * PORTUGAL
*
* This file is provided "AS IS" without warranty of any kind, either
* expressed or implied.
*
* Based upon code by
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <stdlib.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <bsp/irq-generic.h>
#include <libcpu/cpuModel.h>
/*
* Constants
*/
#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this. */
#define SLOW_DOWN_IO 0x80 /* io which does nothing */
#define TWO_MS (uint32_t)(2000) /* TWO_MS = 2000us (sic!) */
#define MSK_NULL_COUNT 0x40 /* bit counter available for reading */
#define CMD_READ_BACK_STATUS 0xE2 /* command read back status */
RTEMS_INTERRUPT_LOCK_DEFINE( /* visible global variable */ ,
rtems_i386_i8254_access_lock, "rtems_i386_i8254_access_lock" );
/*
* Global Variables
*/
volatile uint32_t Ttimer_val;
bool benchmark_timer_find_average_overhead = true;
volatile unsigned int fastLoop1ms, slowLoop1ms;
void (*benchmark_timer_initialize_function)(void) = 0;
benchmark_timer_t (*benchmark_timer_read_function)(void) = 0;
void (*Timer_exit_function)(void) = 0;
/* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
extern void timerisr(void);
void Timer_exit(void);
/*
* Pentium optimized timer handling.
*/
/*
* Timer cleanup routine at RTEMS exit.
*
* NOTE: This routine is not really necessary, since there will be
* a reset at exit.
*/
static void tsc_timer_exit(void)
{
}
static void tsc_timer_initialize(void)
{
static bool First = true;
if (First) {
First = false;
atexit(Timer_exit); /* Try not to hose the system at exit. */
}
Ttimer_val = rdtsc(); /* read starting time */
}
/*
* Read TSC timer value.
*/
static uint32_t tsc_read_timer(void)
{
register uint32_t total;
total = (uint32_t)(rdtsc() - Ttimer_val);
if (benchmark_timer_find_average_overhead)
return total;
if (total < LEAST_VALID)
return 0; /* below timer resolution */
return (total - AVG_OVERHEAD);
}
/*
* Non-Pentium timer handling.
*/
#define US_PER_ISR 250 /* Number of micro-seconds per timer interruption */
/*
* Timer cleanup routine at RTEMS exit. NOTE: This routine is
* not really necessary, since there will be a reset at exit.
*/
static void timerOff(const rtems_raw_irq_connect_data* used)
{
rtems_interrupt_lock_context lock_context;
/*
* disable interrrupt at i8259 level
*/
bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* reset timer mode to standard (DOS) value */
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, 0);
outport_byte(TIMER_CNTR0, 0);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
}
static void timerOn(const rtems_raw_irq_connect_data* used)
{
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* load timer for US_PER_ISR microsecond period */
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
/*
* enable interrrupt at i8259 level
*/
bsp_interrupt_vector_enable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
}
static rtems_raw_irq_connect_data timer_raw_irq_data = {
BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
timerisr,
timerOn,
timerOff,
NULL
};
/*
* Timer cleanup routine at RTEMS exit.
*
* NOTE: This routine is not really necessary, since there will be
* a reset at exit.
*/
static void i386_timer_exit(void)
{
i386_delete_idt_entry (&timer_raw_irq_data);
}
extern void rtems_irq_prologue_0(void);
static void i386_timer_initialize(void)
{
static bool First = true;
if (First) {
rtems_raw_irq_connect_data raw_irq_data = {
BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
rtems_irq_prologue_0,
NULL,
NULL,
NULL
};
First = false;
i386_delete_idt_entry (&raw_irq_data);
atexit(Timer_exit); /* Try not to hose the system at exit. */
if (!i386_set_idt_entry (&timer_raw_irq_data)) {
printk("raw handler connection failed\n");
rtems_fatal_error_occurred(1);
}
}
/* wait for ISR to be called at least once */
Ttimer_val = 0;
while (Ttimer_val == 0)
continue;
Ttimer_val = 0;
}
/*
* Read hardware timer value.
*/
static uint32_t i386_read_timer(void)
{
register uint32_t total, clicks;
register uint8_t lsb, msb;
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
inport_byte(TIMER_CNTR0, lsb);
inport_byte(TIMER_CNTR0, msb);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
clicks = (msb << 8) | lsb;
total = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
if (benchmark_timer_find_average_overhead)
return total;
if (total < LEAST_VALID)
return 0; /* below timer resolution */
return (total - AVG_OVERHEAD);
}
/*
* General timer functions using either TSC-based implementation
* or interrupt-based implementation
*/
void benchmark_timer_initialize(void)
{
static bool First = true;
if (First) {
if (x86_has_tsc()) {
#if defined(DEBUG)
printk("TSC: timer initialization\n");
#endif /* DEBUG */
benchmark_timer_initialize_function = &tsc_timer_initialize;
benchmark_timer_read_function = &tsc_read_timer;
Timer_exit_function = &tsc_timer_exit;
} else {
#if defined(DEBUG)
printk("ISR: timer initialization\n");
#endif /* DEBUG */
benchmark_timer_initialize_function = &i386_timer_initialize;
benchmark_timer_read_function = &i386_read_timer;
Timer_exit_function = &i386_timer_exit;
}
First = false;
}
(*benchmark_timer_initialize_function)();
}
uint32_t benchmark_timer_read(void)
{
return (*benchmark_timer_read_function)();
}
void Timer_exit(void)
{
if ( Timer_exit_function )
return (*Timer_exit_function)();
}
/*
* Set internal benchmark_timer_find_average_overhead flag value.
*/
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}
static unsigned short lastLoadedValue;
/*
* Loads timer 0 with value passed as arguemnt.
*
* Returns: Nothing. Loaded value must be a number of clock bits...
*/
static void loadTimerValue( unsigned short loadedValue )
{
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
lastLoadedValue = loadedValue;
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE);
outport_byte(TIMER_CNTR0, loadedValue & 0xff);
outport_byte(TIMER_CNTR0, (loadedValue >> 8) & 0xff);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
}
/*
* Reads the current value of the timer, and converts the
* number of ticks to micro-seconds.
*
* Returns: number of clock bits elapsed since last load.
*/
static unsigned int readTimer0(void)
{
unsigned short lsb, msb;
unsigned char status;
unsigned int count;
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
outport_byte(
TIMER_MODE,
(TIMER_RD_BACK | (RB_COUNT_0 & ~(RB_NOT_STATUS | RB_NOT_COUNT)))
);
inport_byte(TIMER_CNTR0, status);
inport_byte(TIMER_CNTR0, lsb);
inport_byte(TIMER_CNTR0, msb);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
count = ( msb << 8 ) | lsb ;
if (status & RB_OUTPUT )
count += lastLoadedValue;
return (2*lastLoadedValue - count);
}
static void Timer0Reset(void)
{
loadTimerValue(0xffff);
readTimer0();
}
static void fastLoop (unsigned int loopCount)
{
unsigned int i;
for( i=0; i < loopCount; i++ )outport_byte( SLOW_DOWN_IO, 0 );
}
static void slowLoop (unsigned int loopCount)
{
unsigned int j;
for (j=0; j <100 ; j++) {
fastLoop (loopCount);
}
}
/*
* #define DEBUG_CALIBRATE
*/
void
Calibrate_loop_1ms(void)
{
unsigned int offset, offsetTmp, emptyCall, emptyCallTmp, res, i, j;
unsigned int targetClockBits, currentClockBits;
unsigned int slowLoopGranularity, fastLoopGranularity;
rtems_interrupt_level level;
int retries = 0;
/*
* This code is designed to run before interrupt management
* is enabled and running it on multiple CPUs and or after
* secondary CPUs are bring up seems really broken.
* Disabling of local interrupts is enough.
*/
rtems_interrupt_local_disable(level);
retry:
if ( ++retries >= 5 ) {
printk( "Calibrate_loop_1ms: too many attempts. giving up!!\n" );
while (1);
}
#ifdef DEBUG_CALIBRATE
printk("Calibrate_loop_1ms is starting, please wait (but not too long.)\n");
#endif
targetClockBits = US_TO_TICK(1000);
/*
* Fill up the cache to get a correct offset
*/
Timer0Reset();
readTimer0();
/*
* Compute the minimal offset to apply due to read counter register.
*/
offset = 0xffffffff;
for (i=0; i <1000; i++) {
Timer0Reset();
offsetTmp = readTimer0();
offset += offsetTmp;
}
offset = offset / 1000; /* compute average */
/*
* calibrate empty call
*/
fastLoop (0);
emptyCall = 0;
j = 0;
for (i=0; i <10; i++) {
Timer0Reset();
fastLoop (0);
res = readTimer0();
/* res may be inferior to offset on fast
* machine because we took an average for offset
*/
if (res > offset) {
++j;
emptyCallTmp = res - offset;
emptyCall += emptyCallTmp;
}
}
if (j == 0) emptyCall = 0;
else emptyCall = emptyCall / j; /* compute average */
/*
* calibrate fast loop
*/
Timer0Reset();
fastLoop (10000);
res = readTimer0() - offset;
if (res < emptyCall) {
printk(
"Problem #1 in offset computation in Calibrate_loop_1ms "
" in file libbsp/i386/pc386/timer/timer.c\n"
);
goto retry;
}
fastLoopGranularity = (res - emptyCall) / 10000;
/*
* calibrate slow loop
*/
Timer0Reset();
slowLoop(10);
res = readTimer0();
if (res < offset + emptyCall) {
printk(
"Problem #2 in offset computation in Calibrate_loop_1ms "
" in file libbsp/i386/pc386/timer/timer.c\n"
);
goto retry;
}
slowLoopGranularity = (res - offset - emptyCall)/ 10;
if (slowLoopGranularity == 0) {
printk(
"Problem #3 in offset computation in Calibrate_loop_1ms "
" in file libbsp/i386/pc386/timer/timer.c\n"
);
goto retry;
}
targetClockBits += offset;
#ifdef DEBUG_CALIBRATE
printk("offset = %u, emptyCall = %u, targetClockBits = %u\n",
offset, emptyCall, targetClockBits);
printk("slowLoopGranularity = %u fastLoopGranularity = %u\n",
slowLoopGranularity, fastLoopGranularity);
#endif
slowLoop1ms = (targetClockBits - emptyCall) / slowLoopGranularity;
if (slowLoop1ms != 0) {
fastLoop1ms = targetClockBits % slowLoopGranularity;
if (fastLoop1ms > emptyCall) fastLoop1ms -= emptyCall;
}
else
fastLoop1ms = targetClockBits - emptyCall / fastLoopGranularity;
if (slowLoop1ms != 0) {
/*
* calibrate slow loop
*/
while(1)
{
int previousSign = 0; /* 0 = unset, 1 = incrementing, 2 = decrementing */
Timer0Reset();
slowLoop(slowLoop1ms);
currentClockBits = readTimer0();
if (currentClockBits > targetClockBits) {
if ((currentClockBits - targetClockBits) < slowLoopGranularity) {
/* decrement loop counter anyway to be sure slowLoop(slowLoop1ms) < targetClockBits */
--slowLoop1ms;
break;
}
else {
--slowLoop1ms;
if (slowLoop1ms == 0) break;
if (previousSign == 0) previousSign = 2;
if (previousSign == 1) break;
}
}
else {
if ((targetClockBits - currentClockBits) < slowLoopGranularity) {
break;
}
else {
++slowLoop1ms;
if (previousSign == 0) previousSign = 1;
if (previousSign == 2) break;
}
}
}
}
/*
* calibrate fast loop
*/
if (fastLoopGranularity != 0 ) {
while(1) {
int previousSign = 0; /* 0 = unset, 1 = incrementing, 2 = decrementing */
Timer0Reset();
if (slowLoop1ms != 0) slowLoop(slowLoop1ms);
fastLoop(fastLoop1ms);
currentClockBits = readTimer0();
if (currentClockBits > targetClockBits) {
if ((currentClockBits - targetClockBits) < fastLoopGranularity)
break;
else {
--fastLoop1ms;
if (previousSign == 0) previousSign = 2;
if (previousSign == 1) break;
}
}
else {
if ((targetClockBits - currentClockBits) < fastLoopGranularity)
break;
else {
++fastLoop1ms;
if (previousSign == 0) previousSign = 1;
if (previousSign == 2) break;
}
}
}
}
#ifdef DEBUG_CALIBRATE
printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
#endif
rtems_interrupt_local_enable(level);
}
/*
* loop which waits at least timeToWait ms
*/
void Wait_X_ms( unsigned int timeToWait)
{
unsigned int j;
for (j=0; j<timeToWait ; j++) {
if (slowLoop1ms != 0) slowLoop(slowLoop1ms);
fastLoop(fastLoop1ms);
}
}

View File

@@ -1,56 +0,0 @@
/*-------------------------------------------------------------------------+
| timerisr.s v1.1 - PC386 BSP - 1997/08/07
+--------------------------------------------------------------------------+
| This file contains the PC386 timer interrupt handler.
+--------------------------------------------------------------------------+
| (C) Copyright 1997 -
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
| http://pandora.ist.utl.pt
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
+--------------------------------------------------------------------------+
| Disclaimer:
|
| This file is provided "AS IS" without warranty of any kind, either
| expressed or implied.
+--------------------------------------------------------------------------+
| This code is base on:
| timerisr.s,v 1.5 1995/12/19 20:07:45 joel Exp - go32 BSP
| With the following copyright notice:
| **************************************************************************
| * COPYRIGHT (c) 1989-1999.
| * On-Line Applications Research Corporation (OAR).
| *
| * The license and distribution terms for this file may be
| * found in the file LICENSE in this distribution or at
| * http://www.rtems.org/license/LICENSE.
| **************************************************************************
+--------------------------------------------------------------------------*/
#include <rtems/asm.h>
BEGIN_CODE
EXTERN(Ttimer_val)
/*-------------------------------------------------------------------------+
| Function: rtems_isr timerisr(rtems_vector_number);
| Description: ISR for the timer. The timer is set up to generate an
| interrupt at maximum intervals.
| Global Variables: None.
| Arguments: standard - see RTEMS documentation.
| Returns: standard return value - see RTEMS documentation.
+--------------------------------------------------------------------------*/
PUBLIC(timerisr)
SYM (timerisr):
incl Ttimer_val # another tick
pushl eax
movb $0x20, al
outb al, $0x20 # signal generic End Of Interrupt (EOI) to PIC
popl eax
iret
END_CODE
END

View File

@@ -33,7 +33,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/lm32/shared/clock/ckinit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/lm32/shared/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/lm32/shared/console/uart.c
# timer
librtemsbsp_a_SOURCES += ../shared/timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/lm32/shared/btimer/btimer.c
# Cache
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c

View File

@@ -1,111 +0,0 @@
/* timer.c
*
* This file manages the benchmark timer used by the RTEMS Timing
* Test Suite. Each measured time period is demarcated by calls to
* benchmark_timer_initialize() and benchmark_timer_read().
* benchmark_timer_read() usually returns the number of microseconds
* since benchmark_timer_initialize() exitted.
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
* Micro-Research Finland Oy
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <rtems/bspIo.h>
#include "../include/system_conf.h"
#include "../../shared/clock/clock.h"
static inline int timerread(unsigned int reg)
{
#if ON_SIMULATOR && defined(TIMER0_BASE_ADDRESS)
return *((int*)(TIMER0_BASE_ADDRESS + reg));
#elif defined(TIMER1_BASE_ADDRESS)
return *((int*)(TIMER1_BASE_ADDRESS + reg));
#else
#warning "Benchmarking timer not available!"
return 0;
#endif
}
static inline void timerwrite(unsigned int reg, int value)
{
#if ON_SIMULATOR && defined(TIMER0_BASE_ADDRESS)
*((int*)(TIMER0_BASE_ADDRESS + reg)) = value;
#elif defined(TIMER1_BASE_ADDRESS)
*((int*)(TIMER1_BASE_ADDRESS + reg)) = value;
#endif
}
bool benchmark_timer_find_average_overhead;
void benchmark_timer_initialize( void )
{
/* Set timer period */
timerwrite(LM32_CLOCK_PERIOD, 0xffffffff);
/* Stop timer */
timerwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_STOP);
/* Clear status register */
timerwrite(LM32_CLOCK_SR, 0);
/* Start timer */
timerwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_START);
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 4 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 4 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t ticks;
uint32_t total;
uint32_t status;
ticks = 0xffffffff - timerread(LM32_CLOCK_SNAPSHOT);
status = timerread(LM32_CLOCK_SR);
if (status & LM32_CLOCK_SR_TO)
printk("Timer overflow!\n");
total = ticks / (CPU_FREQUENCY / 1000000);
if ( benchmark_timer_find_average_overhead == true )
return total; /* in XXX microsecond units */
else
{
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -27,7 +27,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/clock/clock-simidle.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m32c/m32cbsp/console/console-io.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m32c/m32cbsp/console/syscalls.S
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m32c/m32cbsp/btimer/btimer.c
# Cache
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c

View File

@@ -1,69 +0,0 @@
/*
* This file implements a stub benchmark timer that is sufficient to
* satisfy linking the RTEMS Benchmarks.
*/
/*
* COPYRIGHT (c) 1989-2001.
* On-Line Applications Research Corporation (OAR).
*/
#include <bsp.h>
#include <rtems/btimer.h>
#include <varvects.h>
bool benchmark_timer_find_average_overhead;
uint32_t benchmark_timer_overhead = 10;
#define TABSR *((uint8_t *)0x340)
#define TA0MR *((uint8_t *)0x356)
#define TA0 *((uint16_t *)0x346)
#define TA0IC *((uint8_t *)0x6c)
static int benchmark_timer_interrupts;
static void __attribute__((interrupt)) timer_ra_interrupt(void);
#define ivec_timer_a0 12
void __attribute__((interrupt))
timer_ra_interrupt(void)
{
benchmark_timer_interrupts++;
TA0IC = 0x05;
}
void benchmark_timer_initialize(void)
{
benchmark_timer_interrupts = 0;
_set_var_vect (timer_ra_interrupt, ivec_timer_a0);
TA0MR = 0x00;
TA0 = 0xffff;
TA0IC = 0x05;
TABSR = 0x55;
}
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t count;
count = 0xFFFF - TA0;
count += benchmark_timer_interrupts * 0xFFFFL;
if (!benchmark_timer_find_average_overhead) {
if ( count > benchmark_timer_overhead )
count -= benchmark_timer_overhead;
else
count = 0;
}
return count;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -31,7 +31,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/av5282/clock/clock.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/av5282/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/av5282/btimer/btimer.c
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,34 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
void
benchmark_timer_initialize(void)
{
int preScaleDivisor = 58;
int div = MCF5282_TIMER_DTMR_CLK_DIV1;
MCF5282_TIMER3_DTRR = 0x2710;
MCF5282_TIMER3_DTMR = 0;
MCF5282_TIMER3_DTMR = MCF5282_TIMER_DTMR_PS(preScaleDivisor - 1) | div |
MCF5282_TIMER_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
uint32_t
benchmark_timer_read(void)
{
return MCF5282_TIMER3_DTCN;
}
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68340/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68340/console/m340uart.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68340/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c

View File

@@ -1,256 +0,0 @@
/*
* ATTENTION: As MC68349 has no built-in Timer, the following code doesn't work
* in a MC68349. You can't use FIFO full mode for the moment, but
* it should be easy to fix this by using an external timer.
*
* Use TIMER 1 for TIMEOUT when using FIFO FULL mode in UART driver
* Use TIMER 2 for timing test suites
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*/
/*
* Geoffroy Montel
* France Telecom - CNET/DSM/TAM/CAT
* 4, rue du Clos Courtel
* 35512 CESSON-SEVIGNE
* FRANCE
*
* e-mail: g_montel@yahoo.com
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <m340uart.h>
#include <m340timer.h>
#include <m68340.h>
#define TIMER1_VECTOR 122
#define TIMER1_IRQ_LEVEL 5
#define TIMER1_INTERRUPT_ARBITRATION 5
#define TIMER2_VECTOR 123
#define TIMER2_IRQ_LEVEL 4
#define TIMER2_INTERRUPT_ARBITRATION 4
#define CLOCK_SPEED 25 /* in Mhz */
#define max(a,b) (((a)>(b)) ? (a) : (b))
void (*Restart_Fifo_Full_A_Timer)(void);
void (*Restart_Check_A_Timer)(void);
void (*Restart_Fifo_Full_B_Timer)(void);
void (*Restart_Check_B_Timer)(void);
int preload = 0;
/*
* __Restart_Fifo_Full_Timer
*
* When a character is received, sets the TIMER to raise an interrupt at
* TIMEOUT. It's necessary to prevent from not getting n-1 characters
* (with n the Uart Fifo size).
*/
static void __Restart_Fifo_Full_Timer (void)
{
TSR1 |= m340_TO;
TCR1 &= ~m340_CPE;
WPREL11 = preload;
TCR1 |= m340_CPE;
}
/*
* __Restart_Check_Timer
*
* When no character has been received recently, check now and then if whether
* a there's a character in the FIFO
*/
static void __Restart_Check_Timer (void)
{
TSR1 |= m340_TO;
TCR1 &= ~m340_CPE;
WPREL11 = 0xFFFF;
TCR1 |= m340_CPE;
}
/*
* __do_nothing
*
* We always restart the fifo full timer with a call to Restart_*_Timer
* if we do not use FIFO full, Restart_X_Timer are set to do __do_nothing
*/
static void __do_nothing (void)
{
}
#define Fifo_Full_on_A \
(m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL && \
m340_uart_config[UART_CHANNEL_A].enable && \
m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
#define Fifo_Full_on_B \
(m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL && \
m340_uart_config[UART_CHANNEL_B].enable && \
m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
/*
* Fifo_Full_benchmark_timer_initialize
*
* initialize Timer 1 for FIFO full mode
*/
void Fifo_Full_benchmark_timer_initialize (void)
{
float max_baud_rate;
int prescaler_output_tap = -1;
int nb_of_clock_ticks = 0;
rtems_isr_entry old_handler;
/*
* USE TIMER 1 for UART FIFO FULL mode
*/
if ( Fifo_Full_on_A || Fifo_Full_on_B ) {
/* Disable the timer */
TCR1 &= ~m340_SWR;
/* Reset the interrupts */
TSR1 &= ~(m340_TO | m340_TG | m340_TC);
/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
* set interrupt arbitration.
*/
TMCR1 = TIMER1_INTERRUPT_ARBITRATION;
/* interrupt priority level and interrupt vector */
TIR1 = TIMER1_VECTOR | (TIMER1_IRQ_LEVEL << 8);
/* compute prescaler */
if ( Fifo_Full_on_A && Fifo_Full_on_B) {
max_baud_rate = max(
m340_uart_config[UART_CHANNEL_A].rx_baudrate,
m340_uart_config[UART_CHANNEL_B].rx_baudrate
);
} else if ( Fifo_Full_on_A ) {
max_baud_rate = m340_uart_config[UART_CHANNEL_A].rx_baudrate;
} else
max_baud_rate = m340_uart_config[UART_CHANNEL_B].rx_baudrate;
/* find out config */
nb_of_clock_ticks = (10/max_baud_rate)*(CLOCK_SPEED*1000000)*1.2;
if (nb_of_clock_ticks < 0xFFFF) {
preload = nb_of_clock_ticks;
prescaler_output_tap = -1;
} else if (nb_of_clock_ticks/2 < 0xFFFF) {
preload = nb_of_clock_ticks/2;
prescaler_output_tap = m340_Divide_by_2;
} else if (nb_of_clock_ticks/4 < 0xFFFF) {
preload = nb_of_clock_ticks/4;
prescaler_output_tap = m340_Divide_by_4;
} else if (nb_of_clock_ticks/8 < 0xFFFF) {
preload = nb_of_clock_ticks/8;
prescaler_output_tap = m340_Divide_by_16;
} else if (nb_of_clock_ticks/16 < 0xFFFF) {
preload = nb_of_clock_ticks/16;
prescaler_output_tap = m340_Divide_by_16;
} else if (nb_of_clock_ticks/32 < 0xFFFF) {
preload = nb_of_clock_ticks/32;
prescaler_output_tap = m340_Divide_by_32;
} else if (nb_of_clock_ticks/64 < 0xFFFF) {
preload = nb_of_clock_ticks/64;
prescaler_output_tap = m340_Divide_by_64;
} else if (nb_of_clock_ticks/128 < 0xFFFF) {
preload = nb_of_clock_ticks/128;
prescaler_output_tap = m340_Divide_by_128;
} else if (nb_of_clock_ticks/256 < 0xFFFF) {
preload = nb_of_clock_ticks/256;
prescaler_output_tap = m340_Divide_by_256;
}
/* Input Capture/Output Compare (ICOC) */
TCR1 = m340_SWR | m340_TO_Enabled | m340_ICOC;
if (prescaler_output_tap!=-1) TCR1 |= prescaler_output_tap | m340_PSE;
/* install interrupt vector */
rtems_interrupt_catch(InterruptHandler, TIMER1_VECTOR, &old_handler);
} /* fifo full mode on a uart */
/* install routines */
if ( Fifo_Full_on_A ) {
Restart_Check_A_Timer = __Restart_Check_Timer;
Restart_Fifo_Full_A_Timer = __Restart_Fifo_Full_Timer;
} else {
Restart_Check_A_Timer = __do_nothing;
Restart_Fifo_Full_A_Timer = __do_nothing;
}
if ( Fifo_Full_on_B ) {
Restart_Check_B_Timer = __Restart_Check_Timer;
Restart_Fifo_Full_B_Timer = __Restart_Fifo_Full_Timer;
} else {
Restart_Check_B_Timer = __do_nothing;
Restart_Fifo_Full_B_Timer = __do_nothing;
}
/* start checking timer */
Restart_Check_A_Timer();
Restart_Check_B_Timer();
}
/*
* benchmark_timer_initialize
*
* init Timer for timing test suites
*/
void benchmark_timer_initialize (void)
{
/* Disable the timer */
TCR2 &= ~m340_SWR;
/* Reset the interrupts */
TSR2 &= ~(m340_TO | m340_TG | m340_TC);
/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
set interrupt arbitration */
TMCR1 = TIMER2_INTERRUPT_ARBITRATION;
/* interrupt priority level and interrupt vector */
TIR1 = TIMER2_VECTOR | (TIMER2_IRQ_LEVEL << 8);
/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
set interrupt arbitration */
TMCR2 = TIMER2_INTERRUPT_ARBITRATION;
/* Preload register 1 */
WPREL21 = 0xFFFF;
/* Input Capture/Output Compare (ICOC) */
TCR2 = m340_SWR | m340_ICOC | m340_PSE | m340_Divide_by_16 | m340_CPE;
}
/*
* benchmark_timer_read
*
* Return timer value in microsecond units
*/
uint32_t benchmark_timer_read (void)
{
/* there's CLOCK_SPEED / 16 micro seconds between two timer
* register decrements.
*/
return (((0xFFFF - TCNTR2) * CLOCK_SPEED) / 16);
}
/*
* benchmark_timer_disable_subtracting_average_overhead
*/
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/gen68360/clock/clock.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68360/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68360/btimer/btimer.c
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,83 +0,0 @@
/*
* Use TIMER 1 and TIMER 2 for Timing Test Suite
* The hardware on the MC68360 makes these routines very simple.
*
* Based on the `gen68302' board support package, and covered by the
* original distribution terms.
*
* W. Eric Norum
* Saskatchewan Accelerator Laboratory
* University of Saskatchewan
* Saskatoon, Saskatchewan, CANADA
* eric@skatter.usask.ca
*/
/*
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
#include <rtems/m68k/m68360.h>
void
benchmark_timer_initialize (void)
{
/*
* Reset timers 1 and 2
*/
m360.tgcr &= ~0x00FF;
m360.tcn1 = 0;
m360.tcn2 = 0;
m360.ter1 = 0xFFFF;
m360.ter2 = 0xFFFF;
/*
* Cascade timers 1 and 2
*/
m360.tgcr |= 0x0080;
/*
* Configure timers 1 and 2 to a single 32-bit, 1 MHz timer.
* HARDWARE:
* Change the `25' to match your processor clock
*/
m360.tmr2 = ((25-1) << 8) | 0x2;
m360.tmr1 = 0;
/*
* Start the timers
*/
m360.tgcr |= 0x0011;
}
/*
* Return timer value in microsecond units
*/
uint32_t
benchmark_timer_read (void)
{
unsigned short val;
val = m360.tcn1;
return val;
}
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/genmcf548x/clock/clock.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/btimer/btimer.c
# IRQ
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c

View File

@@ -1,83 +0,0 @@
/*===============================================================*\
| Project: RTEMS generic mcf548x BSP |
+-----------------------------------------------------------------+
| File: timer.c |
+-----------------------------------------------------------------+
| The file contains the diagnostic timer code of generic MCF548x |
| BSP. |
+-----------------------------------------------------------------+
| Copyright (c) 2007 |
| Embedded Brains GmbH |
| Obere Lagerstr. 30 |
| D-82178 Puchheim |
| Germany |
| rtems@embedded-brains.de |
+-----------------------------------------------------------------+
| |
| Parts of the code has been derived from the "dBUG source code" |
| package Freescale is providing for M548X EVBs. The usage of |
| the modified or unmodified code and it's integration into the |
| generic mcf548x BSP has been done according to the Freescale |
| license terms. |
| |
| The Freescale license terms can be reviewed in the file |
| |
| Freescale_license.txt |
| |
+-----------------------------------------------------------------+
| |
| The generic mcf548x BSP has been developed on the basic |
| structures and modules of the av5282 BSP. |
| |
+-----------------------------------------------------------------+
| |
| The license and distribution terms for this file may be |
| found in the file LICENSE in this distribution or at |
| |
| http://www.rtems.org/license/LICENSE. |
| |
+-----------------------------------------------------------------+
| |
| date history ID |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 12.11.07 1.0 ras |
| |
\*===============================================================*/
/*
* Timer Init
*
* Use the second slice timer (SLT1) as the diagnostic timer.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
#include <mcf548x/mcf548x.h>
bool benchmark_timer_find_average_overhead;
static uint32_t microsecond_timer_value = 0;
void benchmark_timer_initialize(void)
{
MCF548X_SLT_SLTCNT1 = 0xFFFFFFFF;
MCF548X_SLT_SCR1 |= (MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN);
}
/*
* Return timer value in microsecond units
* XLB clock 100 MHz / 1us is equal to 100 counts
*/
uint32_t
benchmark_timer_read(void)
{
microsecond_timer_value = (0xFFFFFFFF - MCF548X_SLT_SCNT1)/100;
return microsecond_timer_value;
}
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf52235/console/console.c
# debugio
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf52235/console/debugio.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf52235/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf5223x.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c

View File

@@ -1,39 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*
* Author: W. Eric Norum <norume@aps.anl.gov>
*
* COPYRIGHT (c) 2005.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
void benchmark_timer_initialize(void)
{
uint32_t preScaleDivisor = bsp_get_CPU_clock_speed() / 1000000;
MCF_DTIM3_DTMR = 0;
MCF_DTIM3_DTMR = MCF_DTIM_DTMR_PS(preScaleDivisor - 1) |
MCF_DTIM_DTMR_CLK_DIV1 | MCF_DTIM_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
benchmark_timer_t benchmark_timer_read(void)
{
return MCF_DTIM3_DTCN;
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -26,7 +26,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/setvec.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mcf5225x/clock/clock.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5225x/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5225x/console/debugio.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5225x/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf5225x.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c

View File

@@ -1,39 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*
* Author: W. Eric Norum <norume@aps.anl.gov>
*
* COPYRIGHT (c) 2005-2010.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
void benchmark_timer_initialize(void)
{
uint32_t preScaleDivisor = bsp_get_CPU_clock_speed() / 1000000;
MCF_DTIM3_DTMR = 0;
MCF_DTIM3_DTMR = MCF_DTIM_DTMR_PS(preScaleDivisor - 1) |
MCF_DTIM_DTMR_CLK_DIV1 | MCF_DTIM_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
benchmark_timer_t benchmark_timer_read(void)
{
return MCF_DTIM3_DTCN;
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mcf5235/clock/clock.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5235/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5235/btimer/btimer.c
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,34 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
void
benchmark_timer_initialize(void)
{
int preScaleDivisor = 0x4A;
int div = MCF5235_TIMER_DTMR_CLK_DIV1;
MCF5235_TIMER_DTRR3 = 0x2710;
MCF5235_TIMER3_DTMR = 0;
MCF5235_TIMER3_DTMR = MCF5235_TIMER_DTMR_PS(preScaleDivisor) | div |
MCF5235_TIMER_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
uint32_t
benchmark_timer_read(void)
{
return MCF5235_TIMER3_DTCN;
}
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -33,7 +33,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mcf5329/clock/clock.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5329/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5329/btimer/btimer.c
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,39 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*
* Author: W. Eric Norum <norume@aps.anl.gov>
*
* COPYRIGHT (c) 2005.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
void benchmark_timer_initialize(void)
{
uint32_t preScaleDivisor = bsp_get_BUS_clock_speed() / 1000000;
MCF_DTIM3_DTMR = 0;
MCF_DTIM3_DTMR = MCF_DTIM_DTMR_PS(preScaleDivisor - 1) |
MCF_DTIM_DTMR_CLK_DIV1 | MCF_DTIM_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
benchmark_timer_t benchmark_timer_read(void)
{
return MCF_DTIM3_DTCN;
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mrm332/console/sci.c
# spurious
librtemsbsp_a_SOURCES += spurious/spinit.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mrm332/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c

View File

@@ -1,60 +0,0 @@
/*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <rtems/btimer.h>
bool benchmark_timer_find_average_overhead;
extern rtems_isr Clock_isr(void);
void benchmark_timer_initialize( void )
{
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* FIND_AVG_OVERHEAD * instructs the routine to return the "raw" count.
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
/*
* Return timer value in 1/2-microsecond units
*/
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t total;
total = 0;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in XXX microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return (total - AVG_OVERHEAD);
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -33,8 +33,8 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mvme147/clock/ckinit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme147/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/timerisr.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme147/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme147/btimer/timerisr.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c

View File

@@ -1,67 +0,0 @@
/*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* MVME147 port for TNI - Telecom Bretagne
* by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr)
* May 1996
*/
#include <rtems/btimer.h>
#include <bsp.h>
#define TIMER_INT_LEVEL 6
#define COUNTDOWN_VALUE 0
/* Allows 0.4096 second delay betwin ints */
/* Each tick is 6.25 us */
int Ttimer_val;
bool benchmark_timer_find_average_overhead;
rtems_isr timerisr(rtems_vector_number);
void benchmark_timer_initialize(void)
{
(void) set_vector(timerisr, TIMER_1_VECTOR, 0); /* install ISR */
Ttimer_val = 0; /* clear timer ISR count */
pcc->timer1_int_control = 0x00; /* Disable T1 Interr. */
pcc->timer1_preload = COUNTDOWN_VALUE;
/* write countdown preload value */
pcc->timer1_control = 0x00; /* load preload value */
pcc->timer1_control = 0x07; /* clear T1 overflow counter, enable counter */
pcc->timer1_int_control = TIMER_INT_LEVEL|0x08;
/* Enable Timer 1 and set its int. level */
}
#define AVG_OVERHEAD 0 /* No need to start/stop the timer to read
its value on the MVME147 PCC: reads are not
synchronized whith the counter updates*/
#define LEAST_VALID 10 /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
uint16_t counter_value;
counter_value = pcc->timer1_count; /* read the counter value */
total = ((Ttimer_val * 0x10000) + counter_value); /* in 6.25 us units */
/* DC note : just look at the assembly generated
to see gcc's impressive optimization ! */
return total;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -1,26 +0,0 @@
/* timer_isr()
*
* This routine provides the ISR for the PCC timer on the MVME147
* board. The timer is set up to generate an interrupt at maximum
* intervals.
*
* MVME147 port for TNI - Telecom Bretagne
* by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr)
* May 1996
*/
#include <rtems/asm.h>
BEGIN_CODE
.set T1_CONTROL_REGISTER, 0xfffe1018 | timer 1 control register
PUBLIC (timerisr)
SYM (timerisr):
orb #0x80, T1_CONTROL_REGISTER | clear T1 int status bit
addql #1, SYM (Ttimer_val) | increment timer value
end_timerisr:
rte
END_CODE
END

View File

@@ -33,8 +33,8 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mvme162/clock/ckinit.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme162/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/timerisr.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme162/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme162/btimer/timerisr.S
# tod
librtemsbsp_a_SOURCES += tod/tod.c

View File

@@ -1,73 +0,0 @@
/*
* This routine initializes the Tick Timer 1 on the MVME162 board.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
* EISCAT Scientific Association. M.Savitski
*
* This material is a part of the MVME162 Board Support Package
* for the RTEMS executive. Its licensing policies are those of the
* RTEMS above.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
/* Periodic tick interval */
#define TICK_INTERVAL 0x10000U
#define TIMER_INT_LEVEL 6
uint32_t Ttimer_val;
bool benchmark_timer_find_average_overhead;
rtems_isr timerisr(rtems_vector_number vector);
void benchmark_timer_initialize(void)
{
(void) set_vector( timerisr, VBR0 * 0x10 + 0x8, 0 );
Ttimer_val = 0; /* clear timer ISR count */
lcsr->vector_base |= MASK_INT; /* unmask VMEchip2 interrupts */
lcsr->intr_clear |= 0x01000000; /* clear pending interrupt */
lcsr->to_ctl = 0xE7; /* prescaler to 1 MHz (see Appendix A1) */
lcsr->timer_cmp_1 = TICK_INTERVAL;
lcsr->timer_cnt_1 = 0; /* clear counter */
lcsr->board_ctl |= 7; /* increment, reset-on-compare, */
/* and clear-overflow-cnt */
lcsr->intr_level[0] |= TIMER_INT_LEVEL; /* set int level */
lcsr->intr_ena |= 0x01000000; /* enable tick timer 1 interrupt */
}
#define AVG_OVERHEAD 3U /* It typically takes 3.0 microseconds */
/* (3 countdowns) to start/stop the timer. */
#define LEAST_VALID 10U /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = (Ttimer_val * TICK_INTERVAL) + lcsr->timer_cnt_1;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one-half microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return (total-AVG_OVERHEAD) >> 1;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -1,44 +0,0 @@
/* timer_isr()
*
* This routine provides the ISR for the Z8036 timer on the MVME136
* board. The timer is set up to generate an interrupt at maximum
* intervals.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
* EISCAT Scientific Association. M.Savitski
*
* This material is a part of the MVME162 Board Support Package
* for the RTEMS executive. Its licensing policies are those of the
* RTEMS above.
*/
#include <rtems/asm.h>
BEGIN_CODE
.set INTR_CLEAR_REG, 0xfff40074 | interrupt clear register
.set RELOAD, 0x01000000 | clear tick 1 interrupt
PUBLIC (Ttimer_val)
PUBLIC (timerisr)
SYM (timerisr):
move.l a0, -(a7) | save a0
movea.l #INTR_CLEAR_REG, a0 | a0 = addr of cmd status reg
ori.l #RELOAD, (a0) | reload countdown
addq.l #1, SYM (Ttimer_val) | increment timer value
move.l (a7)+, a0 | restore a0
rte
END_CODE
END

View File

@@ -31,8 +31,8 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/mvme167/clock/ckinit.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/timerisr.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/btimer/timerisr.S
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,139 +0,0 @@
/**
* @file
*
* This file manages the benchmark timer used by the RTEMS Timing Test Suite.
* Each measured time period is demarcated by calls to
* benchmark_timer_initialize() and benchmark_timer_read().
* benchmark_timer_read() usually returns the number of microseconds
* since benchmark_timer_initialize() exitted.
*
* These functions are prototyped in rtems/btimer.h and
* must be implemented as part of the BSP.
*
* This port does not allow the application to select which timer on the
* MVME167 to use for the timer, nor does it allow the application to
* configure the timer. The timer uses the VMEchip2 Tick Timer #1. This timer
* is distinct from the clock, which uses Tick Timer #2 in the VMEchip2.
*
* All page references are to the MVME166/MVME167/MVME187 Single Board
* Computer Programmer's Reference Guide (MVME187PG/D2) with the April 1993
* supplements/addenda (MVME187PG/D2A1).
*/
/*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Modifications of respective RTEMS file:
* Copyright (c) 1998, National Research Council of Canada
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
/* Periodic tick interval */
#define TICK_INTERVAL 10000UL /* T1's countdown constant (10 ms) */
#define TIMER_INT_LEVEL 6 /* T1's interrupt level */
#define TIMER_VECTOR (VBR0 * 0x10 + 0x8) /* T1 is vector $X8 (p. 2-71)*/
/* Number of interrupts since timer was re-initialized */
uint32_t Ttimer_val;
/*
* Set to true to return raw value. Normally zero. Depends on being allocated
* in the .bss section and on that section being explicitly zeroed at boot
* time.
*/
bool benchmark_timer_find_average_overhead;
rtems_isr timerisr(rtems_vector_number);
/*
* This routine initializes the Tick Timer 1 on the MVME167 board.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* NOTE: This routine may not work if the optimizer is enabled for some
* compilers. The multiple writes may be optimized away.
*
* It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
* The prescaler is used by all VMEchip2 timers, including the VMEbus grant
* timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
* VMEbus global timeout timer. The prescaler value is normally set by the
* boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
* prescaler value should be 0xE7 (page 2-63).
*/
void benchmark_timer_initialize(void)
{
(void) set_vector( timerisr, TIMER_VECTOR, 0 );
Ttimer_val = 0; /* clear timer ISR count */
lcsr->intr_ena &= 0xFEFFFFFF; /* disable tick timer 1 interrupt */
lcsr->intr_clear |= 0x01000000; /* clear tick timer 1 interrupt */
lcsr->intr_level[0] = /* set int level */
(lcsr->intr_level[0] & 0xFFFFFFF0) | TIMER_INT_LEVEL;
lcsr->timer_cmp_1 = TICK_INTERVAL; /* period in compare register */
lcsr->timer_cnt_1 = 0; /* clear tick timer 1 counter */
lcsr->board_ctl |= 7; /* start tick timer 1, reset-on-compare, */
/* and clear overflow counter */
lcsr->intr_ena |= 0x01000000; /* enable tick timer 1 interrupt */
lcsr->vector_base |= MASK_INT; /* unmask VMEchip2 interrupts */
}
#define AVG_OVERHEAD 3UL /* It typically takes 3.0 microseconds */
/* (3 countdowns) to start/stop the timer. */
#define LEAST_VALID 3UL /* Don't trust a value lower than this */
/*
* This routine reads the Tick Timer 1 on the MVME167 board.
*
* Input parameters: NONE
*
* Output parameters: time in microseconds
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = (Ttimer_val * TICK_INTERVAL) + lcsr->timer_cnt_1;
if ( benchmark_timer_find_average_overhead )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
/*
* This routine sets the benchmark_timer_find_average_overhead flag in this
* module.
*
* Input parameters: NONE
*
* Output parameters: time in microseconds
*/
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -1,50 +0,0 @@
/**
* @file
*
* This ISR is used to bump a count of interval "overflow" interrupts which
* have occurred since the timer was started. The number of overflows is taken
* into account in the benchmark_timer_read() routine.
*/
/*
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
* Copyright (c) 1998, National Research Council of Canada
*/
#include <rtems/asm.h>
BEGIN_CODE
.set INTR_CLEAR_REG, 0xfff40074 | interrupt clear register
.set T1_CNTRL_REG, 0xfff40060 | tick timer 1 control register
.set CLEAR_INT, 0x01000000 | clear tick 1 interrupt
.set CLEAR_OVF, 0x00000004 | clear tick 1 overflow counter
PUBLIC (Ttimer_val)
PUBLIC (timerisr)
SYM (timerisr):
move.l a0, -(a7) | save a0
move.l d0, -(a7) | save d0
move.w sr, -(a7) | save ccr
movea.l #INTR_CLEAR_REG, a0 | a0 = addr of intr clr reg
ori.l #CLEAR_INT, (a0) | clear tick timer 1 intr
movea.l #T1_CNTRL_REG, a0 | a0 = addr of t1 cntrl reg
move.l (a0), d0 | read overflow counter
lsr.l #4, d0 | put overflow in low order bits
andi.l #0xF, d0 | keep only overflow
add.l d0, SYM (Ttimer_val) | increment timer value
ori.l #CLEAR_OVF, (a0) | clear overflow counter
move.w (a7)+, sr | restore ccr
move.l (a7)+, d0 | restore d0
move.l (a7)+, a0 | restore a0
rte
END_CODE
END

View File

@@ -31,7 +31,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/m68k/uC5282/clock/clock.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/uC5282/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/uC5282/btimer/btimer.c
if HAS_NETWORKING
librtemsbsp_a_SOURCES += network/network.c

View File

@@ -1,47 +0,0 @@
/*
* Timer Init
*
* Use the last DMA timer (DTIM3) as the diagnostic timer.
*
* Author: W. Eric Norum <norume@aps.anl.gov>
*
* COPYRIGHT (c) 2005.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
void
benchmark_timer_initialize(void)
{
int preScaleDivisor = bsp_get_CPU_clock_speed() / 1000000;
int div = MCF5282_TIMER_DTMR_CLK_DIV1;
if (preScaleDivisor > 256) {
preScaleDivisor /= 16;
div = MCF5282_TIMER_DTMR_CLK_DIV16;
}
MCF5282_TIMER3_DTMR = 0;
MCF5282_TIMER3_DTMR = MCF5282_TIMER_DTMR_PS(preScaleDivisor - 1) | div |
MCF5282_TIMER_DTMR_RST;
}
/*
* Return timer value in microsecond units
*/
uint32_t
benchmark_timer_read(void)
{
return MCF5282_TIMER3_DTCN;
}
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}

View File

@@ -31,7 +31,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/mips/csb350/clock/clockdrv.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/console/console-io.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/btimer/btimer.c
#isr
librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c
librtemsbsp_a_SOURCES += ../shared/irq/irq.c

View File

@@ -1,57 +0,0 @@
/*
* This file implements a benchmark timer using the count/compare
* CP0 registers.
*
* Copyright (c) 2005 by Cogent Computer Systems
* Written by Jay Monkman <jtm@lopingdog.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <assert.h>
#include <bsp.h>
#include <rtems/btimer.h>
bool benchmark_timer_find_average_overhead;
uint32_t tstart;
void benchmark_timer_initialize(void)
{
__asm__ volatile ("mfc0 %0, $9\n" : "=r" (tstart));
/* tick time in picooseconds */
}
#define AVG_OVERHEAD 0 /* It typically takes N instructions */
/* to start/stop the timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this */
/* tx39 simulator can count instructions. :) */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
uint32_t cnt;
__asm__ volatile ("mfc0 %0, $9\n" : "=r" (cnt));
total = cnt - tstart;
total = (total * 1000) / 396; /* convert to nanoseconds */
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -30,7 +30,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/mips/jmr3904/clock/clockdrv.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/jmr3904/console/console-io.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/jmr3904/btimer/btimer.c
#isr
librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c
librtemsbsp_a_SOURCES += ../shared/irq/irq.c

View File

@@ -1,67 +0,0 @@
/*
* This file implements a benchmark timer using a TX39 timer.
*
* NOTE: On the simulator, the count directly reflects instructions.
*
* COPYRIGHT (c) 1989-2000.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <assert.h>
#include <bsp.h>
#include <rtems/btimer.h>
bool benchmark_timer_find_average_overhead;
void benchmark_timer_initialize(void)
{
/*
* Programming the compare register as the maximum value should let
* it run long enough and accurate enough not to require an interrupt.
* but if it ever does generate an interrupt, we will simply fault.
*
* NOTE: This is similar to the clock driver initialization
* with the exception that the divider is disabled and
* the compare register is set to the maximum value.
*/
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_TCR, 0x20 );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_CCDR, 0x3 );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_TRR, 0x0 );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_CPRA, 0xFFFFFFFF );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_TISR, 0x00 );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_ITMR, 0x0001 );
TX3904_TIMER_WRITE( TX3904_TIMER1_BASE, TX3904_TIMER_TCR, 0xe0 );
}
#define AVG_OVERHEAD 0 /* It typically takes N instructions */
/* to start/stop the timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this */
/* tx39 simulator can count instructions. :) */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = TX3904_TIMER_READ( TX3904_TIMER1_BASE, TX3904_TIMER_TRR );
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/nios2/nios2_iss/clock/clock.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/nios2/nios2_iss/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/nios2/nios2_iss/btimer/btimer.c
# Cache
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c

View File

@@ -1,137 +0,0 @@
/*
* This file manages the benchmark timer used by the RTEMS Timing Test
* Suite. Each measured time period is demarcated by calls to
* benchmark_timer_initialize() and benchmark_timer_read().
* benchmark_timer_read() usually returns the number of microseconds
* since benchmark_timer_initialize() exitted.
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*/
/*
* COPYRIGHT (c) 2005-2006 Kolja Waschk rtemsdev/ixo.de
* Derived from no_cpu/no_bsp/timer/timer.c 1.9,
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#define TIMER_WRAPS_AFTER_1MS 0
#include <rtems.h>
#include <rtems/btimer.h>
#include <rtems/score/cpu.h>
#include <bsp.h>
volatile uint32_t Timer_interrupts;
bool benchmark_timer_find_average_overhead;
#define TIMER_REGS ((altera_avalon_timer_regs*)NIOS2_IO_BASE(TIMER_BASE))
static rtems_isr timerisr(rtems_vector_number vector)
{
TIMER_REGS->status = 0;
Timer_interrupts++;
}
void benchmark_timer_initialize( void )
{
/* Disable timer interrupt, stop timer */
TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
set_vector(timerisr, TIMER_VECTOR, 1);
/* Enable interrupt processing */
NIOS2_IENABLE(1 << TIMER_VECTOR);
#if TIMER_WRAPS_AFTER_1MS
/* Writing to periodl/h resets the counter and eventually
stops it. If the timer hasn't been configured with fixed
period, set it to 1 ms now */
TIMER_REGS->period_hi = (TIMER_FREQ/1000)>>16;
TIMER_REGS->period_lo = (TIMER_FREQ/1000)&0xFFFF;
#else
/* Writing to periodl/h resets the counter and eventually
stops it. Set max period */
TIMER_REGS->period_hi = 0xFFFF;
TIMER_REGS->period_lo = 0xFFFF;
#endif
/* For timers that can be stopped, writing to periodl/h
also stopped the timer and we have to manually start it. */
TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_ITO_MSK |
ALTERA_AVALON_TIMER_CONTROL_CONT_MSK |
ALTERA_AVALON_TIMER_CONTROL_START_MSK;
/* This is the most safe place for resetting the overflow
counter - just _after_ we reset the timer. Depending
on the SOPC configuration, the counter may not be
stoppable and it doesn't make sense to assume that
there is any "safe" period before resetting. */
Timer_interrupts = 0;
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 2 /* It typically takes 2 microseconds */
/* to start/stop the timer. */
#define LEAST_VALID AVG_OVERHEAD /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t timer_wraps;
uint32_t timer_snap;
uint32_t timer_ticks;
uint32_t total;
/* Hold timer */
TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
/* Write to request snapshot of timer value */
TIMER_REGS->snap_lo = 0;
/* Get snapshot */
timer_snap = ((TIMER_REGS->snap_hi)<<16) | TIMER_REGS->snap_lo;
timer_wraps = Timer_interrupts;
/* Restart timer */
TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_START_MSK;
#if TIMER_WRAPS_AFTER_1MS
timer_ticks = (TIMER_FREQ / 1000) - 1 - timer_snap;
total = timer_wraps * 1000;
#else
timer_ticks = 0xFFFFFFFF - timer_snap;
total = timer_wraps * 0x80000000 / (TIMER_FREQ / 2000000L);
#endif
total += timer_ticks / (TIMER_FREQ / 1000000L);
if(total < LEAST_VALID) return 0;
if(benchmark_timer_find_average_overhead != TRUE) total-= AVG_OVERHEAD;
return total;
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -25,8 +25,8 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/no_cpu/no_bsp/clock/ckinit.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/no_cpu/no_bsp/console/console.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/timerisr.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/no_cpu/no_bsp/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/no_cpu/no_bsp/btimer/timerisr.c
# shmsupp
librtemsbsp_a_SOURCES += shmsupp/addrconv.c
librtemsbsp_a_SOURCES += shmsupp/getcfg.c

View File

@@ -1,92 +0,0 @@
/* timer.c
*
* This file manages the benchmark timer used by the RTEMS Timing Test
* Suite. Each measured time period is demarcated by calls to
* benchmark_timer_initialize() and benchmark_timer_read(). benchmark_timer_read() usually returns
* the number of microseconds since benchmark_timer_initialize() exitted.
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp.h>
uint32_t Timer_interrupts;
bool benchmark_timer_find_average_overhead;
void benchmark_timer_initialize( void )
{
/*
* Timer has never overflowed. This may not be necessary on some
* implemenations of timer but ....
*/
Timer_interrupts = 0;
/*
* Somehow start the timer
*/
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t clicks;
uint32_t total;
/*
* Read the timer and see how many clicks it has been since we started.
*/
clicks = 0; /* XXX: read some HW here */
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = clicks * 0;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in XXX microsecond units */
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -1,38 +0,0 @@
/**
* @file
*
* If required this ISR is used to bump a count of interval "overflow"
* interrupts which have occurred since the timer was started. The
* number of overflows is taken into account in the benchmark_timer_read()
* routine if necessary.
*
* To reduce overhead this is best to be the "rawest" hardware interupt
* handler you can write. This should be the only interrupt which can
* occur during the measured time period.
*
* @note This file is USUALLY in assembly and is LEAN AND MEAN.
* Any code in this isr is pure overhead which can perturb
* the accuracy of the Timing Test Suite.
*/
/*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
extern uint32_t _Timer_interrupts;
void timerisr( void )
{
/*
* _Timer_interrupts += TIMER_BETWEEN_OVERFLOWS (usually in microseconds)
* return from interrupt
*/
}

View File

@@ -55,7 +55,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/or1k/generic_or1k/console/consol
librtemsbsp_a_SOURCES += ../../../../../../bsps/or1k/generic_or1k/console/uart.c
# Timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/or1k/generic_or1k/btimer/btimer.c
# clock
librtemsbsp_a_SOURCES +=../../../../../../bsps/or1k/generic_or1k/clock/clockdrv.c

View File

@@ -1,64 +0,0 @@
/**
* @file
*
* @ingroup generic_or1k
*
* @brief Benchmark timer support.
*/
/*
* Copyright (c) 2014-2015 by Hesham ALMatary
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <bsp/generic_or1k.h>
#include <rtems/score/or1k-utility.h>
#define OR1K_NANOSECONDS_PER_CLK_CYCLE 10
static bool benchmark_timer_find_average_overhead = false;
static uint64_t benchmark_timer_base;
void benchmark_timer_initialize(void)
{
benchmark_timer_base = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
}
#define AVG_OVERHEAD 0
#define LEAST_VALID 1
benchmark_timer_t benchmark_timer_read( void )
{
uint64_t clicks;
uint64_t total;
uint64_t delta;
/*
* Read the timer and see how many clicks (clock cycles)
* has passed since timer initialization.
*/
clicks = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
delta = clicks - benchmark_timer_base;
/* total in nanoseconds */
total = OR1K_NANOSECONDS_PER_CLK_CYCLE * (delta);
if ( benchmark_timer_find_average_overhead == true )
return total; /* in nanoseconds microsecond units */
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return (total - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -58,7 +58,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qoriq/start/bsprestart.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/qoriq/clock/clock-config.c
# Timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qoriq/btimer/btimer.c
# IRQ
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c

View File

@@ -1,42 +0,0 @@
/**
* @file
*
* @ingroup QorIQ
*
* @brief QorIQ benchmark timer.
*/
/*
* Copyright (c) 2011 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems/btimer.h>
#include <libcpu/powerpc-utility.h>
static benchmark_timer_t benchmark_timer_base;
void benchmark_timer_initialize(void)
{
benchmark_timer_base = ppc_alternate_time_base();
}
benchmark_timer_t benchmark_timer_read(void)
{
return ppc_alternate_time_base() - benchmark_timer_base;
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_average_overhead)
{
/* VOID */
}

View File

@@ -36,7 +36,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/console/console.c
# spi
librtemsbsp_a_SOURCES += spi/spi.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/btimer/btimer.c
# startup
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/start/bspidle.c

View File

@@ -1,101 +0,0 @@
/*===============================================================*\
| Project: RTEMS TQM8xx BSP |
+-----------------------------------------------------------------+
| This file has been adapted to MPC8xx by |
| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
| Copyright (c) 2008 |
| Embedded Brains GmbH |
| Obere Lagerstr. 30 |
| D-82178 Puchheim |
| Germany |
| rtems@embedded-brains.de |
| |
| See the other copyright notice below for the original parts. |
+-----------------------------------------------------------------+
| The license and distribution terms for this file may be |
| found in the file LICENSE in this distribution or at |
| |
| http://www.rtems.org/license/LICENSE. |
| |
+-----------------------------------------------------------------+
| this file contains the console driver |
\*===============================================================*/
/*
* benchmark_timer_initialize()
*
* Use TIMER 1 and TIMER 2 for Timing Test Suite
*
* this is derived from "timer.c" available in the m68k/gen68360 BSP
* adapted by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
*/
/*
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <mpc8xx.h>
bool benchmark_timer_find_average_overhead;
void
benchmark_timer_initialize (void)
{
/*
* Reset timers 1 and 2
*/
m8xx.tgcr &= ~0x00FF;
m8xx.tcn1 = 0;
m8xx.tcn2 = 0;
m8xx.ter1 = 0xFFFF;
m8xx.ter2 = 0xFFFF;
/*
* Cascade timers 1 and 2
*/
m8xx.tgcr |= M8xx_TGCR_CAS2;
/*
* Configure timers 1 and 2 to a single 32-bit, BUS_clock timer.
*/
m8xx.tmr2 = (0 << 8) | 0x2;
m8xx.tmr1 = 0;
/*
* Start the timers
*/
m8xx.tgcr |= 0x0011;
}
/*
* Return timer value in microsecond units
*/
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t retval;
retval = *(uint32_t*)&m8xx.tcn1;
retval = retval * 1000000LL / BSP_bus_frequency;
return retval;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -45,7 +45,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-defa
librtemsbsp_a_SOURCES +=../../../../../../bsps/riscv/riscv_generic/clock/clockdrv.c
# Timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/riscv_generic/btimer/btimer.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled.c

View File

@@ -1,70 +0,0 @@
/*
* Copyright (c) 2015 University of York.
* Hesham Almatary <hesham@alumni.york.ac.uk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/btimer.h>
#include <rtems/score/riscv-utility.h>
extern char bsp_start_vector_table_begin[];
bool benchmark_timer_find_average_overhead;
static void benchmark_timer1_interrupt_handler(void)
{
}
/* Start eCore tiemr 1 usef for profiling and timing analysis */
void benchmark_timer_initialize( void )
{
/* Install interrupt handler for timer 1 */
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/sh/gensh1/clock/ckinit.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/sh/gensh1/clock/delay.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh1/start/cpu_asm.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh1/start/ispsh7032.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh1/btimer/btimer.c
# scitab
librtemsbsp_a_SOURCES += scitab.c
# console

View File

@@ -1,195 +0,0 @@
/**
* @file
* @brief Timer for the Hitachi SH 703X
*/
/*
* Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
* Bernd Becker (becker@faw.uni-ulm.de)
*
* COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* COPYRIGHT (c) 1998.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <rtems/score/sh_io.h>
#include <rtems/score/ispsh7032.h>
#include <rtems/score/iosh7032.h>
extern uint32_t bsp_clicks_per_second;
#define I_CLK_PHI_1 0
#define I_CLK_PHI_2 1
#define I_CLK_PHI_4 2
#define I_CLK_PHI_8 3
/*
* Set I_CLK_PHI to one of the I_CLK_PHI_X values from above to choose
* a PHI/X clock rate.
*/
#define I_CLK_PHI I_CLK_PHI_4
#define CLOCK_SCALE (1<<I_CLK_PHI)
#define ITU1_STARTMASK 0xfd
#define ITU1_SYNCMASK 0xfd
#define ITU1_MODEMASK 0xfd
#define ITU1_TCRMASK (0x00 | I_CLK_PHI)
#define ITU1_TIORMASK 0x88
#define ITU1_STAT_MASK 0xf8
#define ITU1_TIERMASK 0xfc
#define IPRC_ITU1_MASK 0xfff0
#ifndef ITU1_PRIO
#define ITU1_PRIO 15
#endif
#define ITU1_VECTOR OVI1_ISP_V
extern rtems_isr timerisr(void);
static uint32_t Timer_interrupts;
bool benchmark_timer_find_average_overhead;
static uint32_t Timer_HZ ;
void benchmark_timer_initialize( void )
{
uint8_t temp8;
uint16_t temp16;
rtems_interrupt_level level;
rtems_isr *ignored;
Timer_HZ = bsp_clicks_per_second / CLOCK_SCALE ;
/*
* Timer has never overflowed. This may not be necessary on some
* implemenations of timer but ....
*/
Timer_interrupts /* .i */ = 0;
rtems_interrupt_disable( level );
/*
* Somehow start the timer
*/
/* stop Timer 1 */
temp8 = read8(ITU_TSTR) & ITU1_STARTMASK;
write8( temp8, ITU_TSTR );
/* initialize counter 1 */
write16( 0, ITU_TCNT1 );
/* Timer 1 is independent of other timers */
temp8 = read8(ITU_TSNC) & ITU1_SYNCMASK;
write8( temp8, ITU_TSNC );
/* Timer 1, normal mode */
temp8 = read8(ITU_TMDR) & ITU1_MODEMASK;
write8( temp8, ITU_TMDR );
/* Use a Phi/X counter */
write8( ITU1_TCRMASK, ITU_TCR1 );
/* gra and grb are not used */
write8( ITU1_TIORMASK, ITU_TIOR1 );
/* reset all status flags */
temp8 = read8(ITU_TSR1) & ITU1_STAT_MASK;
write8( temp8, ITU_TSR1 );
/* enable overflow interrupt */
write8( ITU1_TIERMASK, ITU_TIER1 );
/* set interrupt priority */
temp16 = read16(INTC_IPRC) & IPRC_ITU1_MASK;
temp16 |= ITU1_PRIO;
write16( temp16, INTC_IPRC );
/* initialize ISR */
_CPU_ISR_install_raw_handler( ITU1_VECTOR, timerisr, &ignored );
rtems_interrupt_enable( level );
/* start timer 1 */
temp8 = read8(ITU_TSTR) | ~ITU1_STARTMASK;
write8( temp8, ITU_TSTR );
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVERHEAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 1 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 0 /* 20 */ /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t cclicks;
uint32_t total ;
/*
* Read the timer and see how many clicks it has been since we started.
*/
cclicks = read16( ITU_TCNT1 ); /* XXX: read some HW here */
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = cclicks + Timer_interrupts * 65536;
if ( benchmark_timer_find_average_overhead )
return total / CLOCK_SCALE; /* in XXX microsecond units */
else
{
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total / CLOCK_SCALE - AVG_OVERHEAD);
}
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}
/* Timer 1 is used */
#pragma interrupt
void timerisr( void )
{
uint8_t temp8;
/* reset the flags of the status register */
temp8 = read8(ITU_TSR1) & ITU1_STAT_MASK;
write8( temp8, ITU_TSR1 );
Timer_interrupts += 1;
}

View File

@@ -37,7 +37,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/sh/gensh2/clock/ckinit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh2/start/cpu_asm.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh2/start/ispsh7045.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh2/btimer/btimer.c
# scitab
librtemsbsp_a_SOURCES += scitab.c
# console

View File

@@ -1,191 +0,0 @@
/**
* @file
* @brief Timer for the Hitachi SH 704X
*/
/*
* Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
* Bernd Becker (becker@faw.uni-ulm.de)
*
* COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* COPYRIGHT (c) 1998.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <rtems/score/sh_io.h>
#include <rtems/score/iosh7045.h>
extern uint32_t bsp_clicks_per_second;
/*
* We use a Phi/4 timer
*/
#define SCALE (Timer_MHZ/4)
#define MTU1_STARTMASK 0xfd
#define MTU1_SYNCMASK 0xfd
#define MTU1_MODEMASK 0xc0
#define MTU1_TCRMASK 0x01
#define MTU1_TIORMASK 0x88
#define MTU1_STAT_MASK 0xf8
#define MTU1_TIERMASK 0xfc
#define IPRC_MTU1_MASK 0xfff0
#ifndef MTU1_PRIO
#define MTU1_PRIO 15
#endif
#define MTU1_VECTOR 86
extern rtems_isr timerisr(void);
static uint32_t Timer_interrupts;
bool benchmark_timer_find_average_overhead;
static uint32_t Timer_MHZ ;
void benchmark_timer_initialize( void )
{
uint8_t temp8;
uint16_t temp16;
rtems_interrupt_level level;
rtems_isr *ignored;
Timer_MHZ = bsp_clicks_per_second / 1000000 ;
/*
* Timer has never overflowed. This may not be necessary on some
* implemenations of timer but ....
*/
Timer_interrupts /* .i */ = 0;
rtems_interrupt_disable( level );
/*
* Somehow start the timer
*/
/* stop Timer 1 */
temp8 = read8(MTU_TSTR) & MTU1_STARTMASK;
write8( temp8, MTU_TSTR );
/* initialize counter 1 */
write16( 0, MTU_TCNT1);
/* Timer 1 is independent of other timers */
temp8 = read8(MTU_TSYR) & MTU1_SYNCMASK;
write8( temp8, MTU_TSYR );
/* Timer 1, normal mode */
temp8 = read8(MTU_TMDR1) & MTU1_MODEMASK;
write8( temp8, MTU_TMDR1 );
/* x0000000
* |||||+++--- Internal Clock
* |||++------ Count on rising edge
* |++-------- disable TCNT clear
* +---------- don`t care
*/
write8( MTU1_TCRMASK, MTU_TCR1 );
/* gra and grb are not used */
write8( MTU1_TIORMASK, MTU_TIOR1 );
/* reset all status flags */
temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
write8( temp8, MTU_TSR1 );
/* enable overflow interrupt */
write8( MTU1_TIERMASK, MTU_TIER1 );
/* set interrupt priority */
temp16 = read16(INTC_IPRC) & IPRC_MTU1_MASK;
temp16 |= MTU1_PRIO;
write16( temp16, INTC_IPRC);
/* initialize ISR */
_CPU_ISR_install_raw_handler( MTU1_VECTOR, timerisr, &ignored );
rtems_interrupt_enable( level );
/* start timer 1 */
temp8 = read8(MTU_TSTR) | ~MTU1_STARTMASK;
write8( temp8, MTU_TSTR );
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVERHEAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 1 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 0 /* 20 */ /* Don't trust a clicks value lower than this */
benchmark_timer_t benchmark_timer_read( void )
{
uint32_t clicks;
uint32_t total ;
/*
* Read the timer and see how many clicks it has been since we started.
*/
clicks = read16( MTU_TCNT1 ); /* XXX: read some HW here */
/*
* Total is calculated by taking into account the number of timer overflow
* interrupts since the timer was initialized and clicks since the last
* interrupts.
*/
total = clicks + Timer_interrupts * 65536;
if ( benchmark_timer_find_average_overhead )
return total / SCALE; /* in XXX microsecond units */
else
{
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total / SCALE - AVG_OVERHEAD) ;
}
}
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}
/* Timer 1 is used */
#pragma interrupt
void timerisr( void )
{
uint8_t temp8;
/* reset the flags of the status register */
temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
write8( temp8, MTU_TSR1 );
Timer_interrupts += 1;
}

View File

@@ -28,7 +28,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh4/start/cpu_asm.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh4/start/ispsh7750.c
librtemsbsp_a_SOURCES +=../../../../../../bsps/sh/gensh4/clock/ckinit.c
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh4/btimer/btimer.c
# console
librtemsbsp_a_SOURCES += ../../../../../../bsps/sh/gensh4/console/console.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c

View File

@@ -1,269 +0,0 @@
/**
* @file
* @brief Timer driver for the Hitachi SH 7750
*/
/*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* COPYRIGHT (c) 1998.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <rtems/btimer.h>
#include <rtems/score/sh_io.h>
#include <rtems/score/iosh7750.h>
extern uint32_t bsp_clicks_per_second;
#ifndef TIMER_PRIO
#define TIMER_PRIO 15
#endif
/* Timer prescaler division ratio */
#define TIMER_PRESCALER 4
#define TCR1_TPSC SH7750_TCR_TPSC_DIV4
#define TIMER_VECTOR SH7750_EVT_TO_NUM(SH7750_EVT_TUNI1)
extern rtems_isr timerisr(void);
static uint32_t Timer_interrupts;
/* Counter should be divided to this value to obtain time in microseconds */
static uint32_t microseconds_divider;
/* Interrupt period in microseconds */
static uint32_t microseconds_per_int;
bool benchmark_timer_find_average_overhead;
/* benchmark_timer_initialize --
* Initialize Timer 1 to operate as a RTEMS benchmark timer:
* - determine timer clock frequency
* - install timer interrupt handler
* - configure the Timer 1 hardware
* - start the timer
*
* PARAMETERS:
* none
*
* RETURNS:
* none
*/
void
benchmark_timer_initialize(void)
{
uint8_t temp8;
uint16_t temp16;
rtems_interrupt_level level;
rtems_isr *ignored;
int cpudiv = 1;
int tidiv = 1;
Timer_interrupts = 0;
rtems_interrupt_disable(level);
/* Get CPU frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_IFC)
{
case SH7750_FRQCR_IFCDIV1:
cpudiv = 1;
break;
case SH7750_FRQCR_IFCDIV2:
cpudiv = 2;
break;
case SH7750_FRQCR_IFCDIV3:
cpudiv = 3;
break;
case SH7750_FRQCR_IFCDIV4:
cpudiv = 4;
break;
case SH7750_FRQCR_IFCDIV6:
cpudiv = 6;
break;
case SH7750_FRQCR_IFCDIV8:
cpudiv = 8;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
/* Get peripheral module frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_PFC)
{
case SH7750_FRQCR_PFCDIV2:
tidiv = 2 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV3:
tidiv = 3 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV4:
tidiv = 4 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV6:
tidiv = 6 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV8:
tidiv = 8 * TIMER_PRESCALER;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
microseconds_divider = bsp_clicks_per_second * cpudiv / (tidiv * 1000000);
microseconds_per_int = 0xFFFFFFFF / microseconds_divider;
/*
* Hardware specific initialization
*/
/* Stop the Timer 0 */
temp8 = read8(SH7750_TSTR);
temp8 &= ~SH7750_TSTR_STR1;
write8(temp8, SH7750_TSTR);
/* Establish interrupt handler */
_CPU_ISR_install_raw_handler( TIMER_VECTOR, timerisr, &ignored );
/* Reset timer constant and counter */
write32(0xFFFFFFFF, SH7750_TCOR1);
write32(0xFFFFFFFF, SH7750_TCNT1);
/* Select timer mode */
write16(
SH7750_TCR_UNIE | /* Enable Underflow Interrupt */
SH7750_TCR_CKEG_RAISE | /* Count on rising edge */
TCR1_TPSC, /* Timer prescaler ratio */
SH7750_TCR1);
/* Set timer interrupt priority */
temp16 = read16(SH7750_IPRA);
temp16 = (temp16 & ~SH7750_IPRA_TMU1) | (TIMER_PRIO << SH7750_IPRA_TMU1_S);
write16(temp16, SH7750_IPRA);
rtems_interrupt_enable(level);
/* Start the Timer 1 */
temp8 = read8(SH7750_TSTR);
temp8 |= SH7750_TSTR_STR1;
write8(temp8, SH7750_TSTR);
}
/*
* The following controls the behavior of benchmark_timer_read().
*
* AVG_OVERHEAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 0 /* 20 */ /* Don't trust a clicks value lower than this */
/* benchmark_timer_read --
* Read timer value in microsecond units since timer start.
*
* PARAMETERS:
* none
*
* RETURNS:
* number of microseconds since timer has been started
*/
benchmark_timer_t
benchmark_timer_read(void)
{
uint32_t clicks;
uint32_t ints;
uint32_t total;
rtems_interrupt_level level;
uint32_t tcr;
rtems_interrupt_disable(level);
clicks = 0xFFFFFFFF - read32(SH7750_TCNT1);
tcr = read32(SH7750_TCR1);
ints = Timer_interrupts;
rtems_interrupt_enable(level);
/* Handle the case when timer overflowed but interrupt was not processed */
if ((clicks > 0xFF000000) && ((tcr & SH7750_TCR_UNF) != 0))
{
ints++;
}
total = microseconds_per_int * ints + (clicks / microseconds_divider);
if ( benchmark_timer_find_average_overhead )
return total; /* in microsecond units */
else
{
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD) ;
}
}
/* benchmark_timer_disable_subtracting_average_overhead --
* This routine is invoked by the "Check Timer" (tmck) test in the
* RTEMS Timing Test Suite. It makes the benchmark_timer_read routine not
* subtract the overhead required to initialize and read the benchmark
* timer.
*
* PARAMETERS:
* find_flag - boolean flag, true if overhead must not be subtracted.
*
* RETURNS:
* none
*/
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
benchmark_timer_find_average_overhead = find_flag;
}
/* timerisr --
* Timer interrupt handler routine. This function invoked on timer
* underflow event; once per 2^32 clocks. It should reset the timer
* event and increment timer interrupts counter.
*/
void
timerisr(void)
{
uint8_t temp8;
/* reset the flags of the status register */
temp8 = read8(SH7750_TCR1) & ~SH7750_TCR_UNF;
write8(temp8, SH7750_TCR1);
Timer_interrupts += 1;
}

View File

@@ -50,7 +50,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/console/debugputs.c
# clock
librtemsbsp_a_SOURCES +=../../../../../../bsps/sparc/erc32/clock/ckinit.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/btimer/btimer.c
# IRQ
librtemsbsp_a_SOURCES += ../shared/irq/irq-shared.c

View File

@@ -1,81 +0,0 @@
/* timer.c
*
* This file implements a benchmark timer using the General Purpose Timer on
* the MEC.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Ported to ERC32 implementation of the SPARC by On-Line Applications
* Research Corporation (OAR) under contract to the European Space
* Agency (ESA).
*
* ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995.
* European Space Agency.
*/
#include <bsp.h>
#include <rtems/btimer.h>
bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false;
void benchmark_timer_initialize(void)
{
/*
* Timer runs long and accurate enough not to require an interrupt.
*/
if ( benchmark_timer_is_initialized == false ) {
/* approximately 1 us per countdown */
ERC32_MEC.General_Purpose_Timer_Scalar = CLOCK_SPEED - 1;
ERC32_MEC.General_Purpose_Timer_Counter = 0xffffffff;
} else {
benchmark_timer_is_initialized = true;
}
ERC32_MEC_Set_General_Purpose_Timer_Control(
ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER
);
ERC32_MEC_Set_General_Purpose_Timer_Control(
ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING
);
}
#define AVG_OVERHEAD 12 /* It typically takes 3.0 microseconds */
/* to start/stop the timer. */
#define LEAST_VALID 13 /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = ERC32_MEC.General_Purpose_Timer_Counter;
total = 0xffffffff - total;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -66,8 +66,8 @@ librtemsbsp_a_SOURCES += ../shared/amba/ambapp_show.c
librtemsbsp_a_SOURCES += ../shared/amba/ahbstat.c
# Clock Driver and Timer Library
librtemsbsp_a_SOURCES += ../shared/timer/gptimer.c
librtemsbsp_a_SOURCES += ../shared/timer/tlib.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/gptimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/tlib.c
# PCI
librtemsbsp_a_SOURCES += ../shared/pci/grpci2.c
@@ -137,7 +137,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/cache.c
# griommu
librtemsbsp_a_SOURCES += ../shared/iommu/griommu.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/btimer/btimer.c
# TM/TC
librtemsbsp_a_SOURCES += ../shared/tmtc/grtc.c

View File

@@ -1,83 +0,0 @@
/**
* @file
* @ingroup sparc_leon2
* @brief Implement a benchmark timer using timer 2
*/
/* timer.c
*
* This file implements a benchmark timer using timer 2.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Ported to LEON implementation of the SPARC by On-Line Applications
* Research Corporation (OAR) under contract to the European Space
* Agency (ESA).
*
* LEON modifications of respective RTEMS file: COPYRIGHT (c) 1995.
* European Space Agency.
*/
#include <bsp.h>
#include <rtems/btimer.h>
bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false;
void benchmark_timer_initialize(void)
{
/*
* Timer runs long and accurate enough not to require an interrupt.
*/
if ( benchmark_timer_is_initialized == false ) {
/* approximately 1 us per countdown */
LEON_REG.Timer_Counter_2 = 0xffffff;
LEON_REG.Timer_Reload_2 = 0xffffff;
} else {
benchmark_timer_is_initialized = true;
}
LEON_REG.Timer_Control_2 = (
LEON_REG_TIMER_COUNTER_ENABLE_COUNTING |
LEON_REG_TIMER_COUNTER_LOAD_COUNTER
);
}
#define AVG_OVERHEAD 3 /* It typically takes 3.0 microseconds */
/* to start/stop the timer. */
#define LEAST_VALID 2 /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
total = LEON_REG.Timer_Counter_2;
total = 0xffffff - total;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -60,9 +60,9 @@ librtemsbsp_a_SOURCES += ../shared/amba/ambapp_show.c
librtemsbsp_a_SOURCES += ../shared/amba/ahbstat.c
# Clock Driver and Timer Library
librtemsbsp_a_SOURCES += ../shared/timer/gptimer.c
librtemsbsp_a_SOURCES += ../shared/timer/tlib.c
librtemsbsp_a_SOURCES += ../shared/timer/tlib_ckinit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/gptimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/tlib.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/tlib_ckinit.c
# non-Driver Manager Clock Implementation
librtemsbsp_a_SOURCES +=../../../../../../bsps/sparc/leon3/clock/ckinit.c
@@ -151,8 +151,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/cache.c
# griommu
librtemsbsp_a_SOURCES += ../shared/iommu/griommu.c
# timer
librtemsbsp_a_SOURCES += timer/timer.c
librtemsbsp_a_SOURCES += timer/watchdog.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/btimer/btimer.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/btimer/watchdog.c
# GR712
librtemsbsp_a_SOURCES += ../shared/ascs/grascs.c

View File

@@ -1,85 +0,0 @@
/* timer.c
*
* This file implements a benchmark timer using timer 2.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* Ported to LEON implementation of the SPARC by On-Line Applications
* Research Corporation (OAR) under contract to the European Space
* Agency (ESA).
*
* LEON modifications of respective RTEMS file: COPYRIGHT (c) 1995.
* European Space Agency.
*/
#include <bsp.h>
#include <rtems/btimer.h>
#if defined(RTEMS_MULTIPROCESSING)
#define LEON3_TIMER_INDEX \
((rtems_configuration_get_user_multiprocessing_table()) ? \
(rtems_configuration_get_user_multiprocessing_table()->node) - 1 : 1)
#else
#define LEON3_TIMER_INDEX 0
#endif
bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false;
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
void benchmark_timer_initialize(void)
{
/*
* Timer runs long and accurate enough not to require an interrupt.
*/
if (LEON3_Timer_Regs) {
if ( benchmark_timer_is_initialized == false ) {
/* approximately 1 us per countdown */
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].reload = 0xffffff;
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].value = 0xffffff;
} else {
benchmark_timer_is_initialized = true;
}
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].ctrl =
GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_LD;
}
}
#define AVG_OVERHEAD 3 /* It typically takes 3.0 microseconds */
/* to start/stop the timer. */
#define LEAST_VALID 2 /* Don't trust a value lower than this */
benchmark_timer_t benchmark_timer_read(void)
{
uint32_t total;
if (LEON3_Timer_Regs) {
total = LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].value;
total = 0xffffff - total;
if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return total - AVG_OVERHEAD;
}
return 0;
}
void benchmark_timer_disable_subtracting_average_overhead(
bool find_flag
)
{
benchmark_timer_find_average_overhead = find_flag;
}

View File

@@ -1,90 +0,0 @@
/* GPTIMER Watchdog timer routines. On some systems the first GPTIMER
* core's last Timer instance underflow signal is connected to system
* reset.
*
* COPYRIGHT (c) 2012.
* Cobham Gaisler AB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h>
#include <bsp/watchdog.h>
#include <grlib.h>
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
struct gptimer_watchdog_priv {
struct gptimer_regs *regs;
struct gptimer_timer_regs *timer;
int timerno;
};
struct gptimer_watchdog_priv bsp_watchdogs[1];
int bsp_watchdog_count = 0;
int bsp_watchdog_init(void)
{
int timercnt;
if (!LEON3_Timer_Regs)
return 0;
/* Get Watchdogs in system, this is implemented for one GPTIMER core
* only.
*
* First watchdog is a special case, we can get the first timer core by
* looking at LEON3_Timer_Regs, the watchdog within a timer core is
* always the last timer. Unfortunately we can not know it the watchdog
* functionality is available or not, we assume that it is if we
* reached this function.
*/
bsp_watchdogs[0].regs = (struct gptimer_regs *)LEON3_Timer_Regs;
/* Find Timer that has watchdog functionality */
timercnt = bsp_watchdogs[0].regs->cfg & 0x7;
if (timercnt < 2) /* First timer system clock timer */
return 0;
bsp_watchdogs[0].timerno = timercnt - 1;
bsp_watchdogs[0].timer = &bsp_watchdogs[0].regs->timer[bsp_watchdogs[0].timerno];
bsp_watchdog_count = 1;
return bsp_watchdog_count;
}
void bsp_watchdog_reload(int watchdog, unsigned int reload_value)
{
if (bsp_watchdog_count == 0)
bsp_watchdog_init();
if (bsp_watchdog_count <= watchdog)
return;
/* Kick watchdog, and clear interrupt pending bit */
bsp_watchdogs[watchdog].timer->reload = reload_value;
bsp_watchdogs[watchdog].timer->ctrl =
(GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_EN) |
(bsp_watchdogs[watchdog].timer->ctrl & ~(1<<4));
}
void bsp_watchdog_stop(int watchdog)
{
if (bsp_watchdog_count == 0)
bsp_watchdog_init();
if (bsp_watchdog_count <= watchdog)
return;
/* Stop watchdog timer */
bsp_watchdogs[watchdog].timer->ctrl = 0;
}
/* Use watchdog timer to reset system */
void bsp_watchdog_system_reset(void)
{
sparc_disable_interrupts();
bsp_watchdog_reload(0, 1);
}

View File

@@ -1,544 +0,0 @@
/* This file contains the driver for the GRLIB GPTIMER timers port. The driver
* is implemented by using the tlib.c simple timer layer and the Driver
* Manager.
*
* The Driver can be configured using driver resources:
*
* - timerStart Timer Index if first Timer, this parameters is typically used
* in AMP systems for resource allocation. The Timers before
* timerStart will not be accessed.
* - timerCnt Number of timers that the driver will use, this parameters is
* typically used in AMP systems for resource allocation between
* OS instances.
* - prescaler Base prescaler, normally set by bootloader but can be
* overridden. The default scaler reload value set by bootloader
* is so that Timers operate in 1MHz. Setting the prescaler to a
* lower value increase the accuracy of the timers but shortens
* the time until underflow happens.
* - clockTimer Used to select a particular timer to be the system clock
* timer. This is useful when multiple GPTIMERs cores are
* available, or in AMP systems. By default the TLIB selects the
* first timer registered as system clock timer.
*
* The BSP define APBUART_INFO_AVAIL in order to add the info routine
* used for debugging.
*
* COPYRIGHT (c) 2010.
* Cobham Gaisler AB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp.h>
#include <stdlib.h>
#include <string.h>
#include <drvmgr/drvmgr.h>
#include <drvmgr/ambapp_bus.h>
#include <grlib.h>
#include <bsp/gptimer.h>
#include <bsp/tlib.h>
#if defined(LEON3)
#include <leon.h>
#endif
#ifdef GPTIMER_INFO_AVAIL
#include <stdio.h>
#endif
#ifdef RTEMS_SMP
#include <rtems/score/processormask.h>
#include <rtems/score/smpimpl.h>
#endif
/* GPTIMER Core Configuration Register (READ-ONLY) */
#define GPTIMER_CFG_TIMERS_BIT 0
#define GPTIMER_CFG_IRQ_BIT 3
#define GPTIMER_CFG_SI_BIT 8
#define GPTIMER_CFG_DF_BIT 9
#define GPTIMER_CFG_TIMERS (0x7<<GPTIMER_CFG_TIMERS_BIT)
#define GPTIMER_CFG_IRQ (0x1f<<GPTIMER_CFG_IRQ_BIT)
#define GPTIMER_CFG_SI (1<<GPTIMER_CFG_SI_BIT)
#define GPTIMER_CFG_DF (1<<GPTIMER_CFG_DF_BIT)
/* GPTIMER Timer Control Register */
#define GPTIMER_CTRL_EN_BIT 0
#define GPTIMER_CTRL_RS_BIT 1
#define GPTIMER_CTRL_LD_BIT 2
#define GPTIMER_CTRL_IE_BIT 3
#define GPTIMER_CTRL_IP_BIT 4
#define GPTIMER_CTRL_CH_BIT 5
#define GPTIMER_CTRL_DH_BIT 6
#define GPTIMER_CTRL_EN (1<<GPTIMER_CTRL_EN_BIT)
#define GPTIMER_CTRL_RS (1<<GPTIMER_CTRL_RS_BIT)
#define GPTIMER_CTRL_LD (1<<GPTIMER_CTRL_LD_BIT)
#define GPTIMER_CTRL_IE (1<<GPTIMER_CTRL_IE_BIT)
#define GPTIMER_CTRL_IP (1<<GPTIMER_CTRL_IP_BIT)
#define GPTIMER_CTRL_CH (1<<GPTIMER_CTRL_CH_BIT)
#define GPTIMER_CTRL_DH (1<<GPTIMER_CTRL_DH_BIT)
#define DBG(x...)
/* GPTIMER timer private */
struct gptimer_timer {
struct tlib_dev tdev; /* Must be first in struct */
struct gptimer_timer_regs *tregs;
char index; /* Timer Index in this driver */
char tindex; /* Timer Index In Hardware */
unsigned char irq_ack_mask;
};
/* GPTIMER Core private */
struct gptimer_priv {
struct drvmgr_dev *dev;
struct gptimer_regs *regs;
unsigned int base_clk;
unsigned int base_freq;
unsigned int widthmask;
char separate_interrupt;
char isr_installed;
/* Structure per Timer unit, the core supports up to 8 timers */
int timer_cnt;
struct gptimer_timer timers[0];
};
void gptimer_isr(void *data);
#if 0
void gptimer_tlib_irq_register(struct tlib_drv *tdrv, tlib_isr_t func, void *data)
{
struct gptimer_priv *priv = (struct gptimer_priv *)tdrv;
if ( SHARED ...)
drvmgr_interrupt_register();
}
#endif
/******************* Driver manager interface ***********************/
/* Driver prototypes */
static struct tlib_drv gptimer_tlib_drv;
int gptimer_device_init(struct gptimer_priv *priv);
int gptimer_init1(struct drvmgr_dev *dev);
#ifdef GPTIMER_INFO_AVAIL
static int gptimer_info(
struct drvmgr_dev *dev,
void (*print_line)(void *p, char *str),
void *p, int, char *argv[]);
#define GTIMER_INFO_FUNC gptimer_info
#else
#define GTIMER_INFO_FUNC NULL
#endif
struct drvmgr_drv_ops gptimer_ops =
{
.init = {gptimer_init1, NULL, NULL, NULL},
.remove = NULL,
.info = GTIMER_INFO_FUNC,
};
struct amba_dev_id gptimer_ids[] =
{
{VENDOR_GAISLER, GAISLER_GPTIMER},
{VENDOR_GAISLER, GAISLER_GRTIMER},
{0, 0} /* Mark end of table */
};
struct amba_drv_info gptimer_drv_info =
{
{
DRVMGR_OBJ_DRV, /* Driver */
NULL, /* Next driver */
NULL, /* Device list */
DRIVER_AMBAPP_GAISLER_GPTIMER_ID,/* Driver ID */
"GPTIMER_DRV", /* Driver Name */
DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
&gptimer_ops,
NULL, /* Funcs */
0, /* No devices yet */
0,
},
&gptimer_ids[0]
};
void gptimer_register_drv (void)
{
DBG("Registering GPTIMER driver\n");
drvmgr_drv_register(&gptimer_drv_info.general);
}
int gptimer_init1(struct drvmgr_dev *dev)
{
struct gptimer_priv *priv;
struct gptimer_regs *regs;
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
int timer_hw_cnt, timer_cnt, timer_start;
int i, size;
struct gptimer_timer *timer;
union drvmgr_key_value *value;
unsigned char irq_ack_mask;
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo;
if ( ambadev == NULL ) {
return -1;
}
pnpinfo = &ambadev->info;
regs = (struct gptimer_regs *)pnpinfo->apb_slv->start;
DBG("GPTIMER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
/* Get number of Timers */
timer_hw_cnt = regs->cfg & GPTIMER_CFG_TIMERS;
/* Let user spelect a range of timers to be used. In AMP systems
* it is sometimes neccessary to leave timers for other CPU instances.
*
* The default operation in AMP is to shared the timers within the
* first GPTIMER core as below. This can of course be overrided by
* driver resources.
*/
timer_cnt = timer_hw_cnt;
timer_start = 0;
#if defined(RTEMS_MULTIPROCESSING) && defined(LEON3)
if ((dev->minor_drv == 0) && drvmgr_on_rootbus(dev)) {
timer_cnt = 1;
timer_start = LEON3_Cpu_Index;
}
#endif
value = drvmgr_dev_key_get(dev, "timerStart", DRVMGR_KT_INT);
if ( value) {
timer_start = value->i;
timer_cnt = timer_hw_cnt - timer_start;
}
value = drvmgr_dev_key_get(dev, "timerCnt", DRVMGR_KT_INT);
if ( value && (value->i < timer_cnt) ) {
timer_cnt = value->i;
}
/* Allocate Common Timer Description, size depends on how many timers
* are present.
*/
size = sizeof(struct gptimer_priv) +
timer_cnt*sizeof(struct gptimer_timer);
priv = dev->priv = (struct gptimer_priv *)malloc(size);
if ( !priv )
return DRVMGR_NOMEM;
memset(priv, 0, size);
priv->dev = dev;
priv->regs = regs;
/* The Base Frequency of the GPTIMER core is the same as the
* frequency of the AMBA bus it is situated on.
*/
drvmgr_freq_get(dev, DEV_APB_SLV, &priv->base_clk);
/* This core will may provide important Timer functionality
* to other drivers and the RTEMS kernel, the Clock driver
* may for example use this device. So the Timer driver must be
* initialized in the first iiitialization stage.
*/
/*** Initialize Hardware ***/
/* If user request to set prescaler, we will do that. However, note
* that doing so for the Root-Bus GPTIMER may affect the RTEMS Clock
* so that Clock frequency is wrong.
*/
value = drvmgr_dev_key_get(priv->dev, "prescaler", DRVMGR_KT_INT);
if ( value )
regs->scaler_reload = value->i;
/* Get Frequency that the timers are operating in (after prescaler) */
priv->base_freq = priv->base_clk / (priv->regs->scaler_reload + 1);
/* Stop Timer and probe Pending bit. In newer hardware the
* timer has pending bit is cleared by writing a one to it,
* whereas older versions it is cleared with a zero.
*/
priv->regs->timer[timer_start].ctrl = GPTIMER_CTRL_IP;
if ((priv->regs->timer[timer_start].ctrl & GPTIMER_CTRL_IP) != 0)
irq_ack_mask = ~GPTIMER_CTRL_IP;
else
irq_ack_mask = ~0;
/* Probe timer register width mask */
priv->regs->timer[timer_start].value = 0xffffffff;
priv->widthmask = priv->regs->timer[timer_start].value;
priv->timer_cnt = timer_cnt;
for (i=0; i<timer_cnt; i++) {
timer = &priv->timers[i];
timer->index = i;
timer->tindex = i + timer_start;
timer->tregs = &regs->timer[(int)timer->tindex];
timer->tdev.drv = &gptimer_tlib_drv;
timer->irq_ack_mask = irq_ack_mask;
/* Register Timer at Timer Library */
tlib_dev_reg(&timer->tdev);
}
/* Check Interrupt support implementation, two cases:
* A. All Timers share one IRQ
* B. Each Timer have an individual IRQ. The number is:
* BASE_IRQ + timer_index
*/
priv->separate_interrupt = (regs->cfg & GPTIMER_CFG_SI) != 0;
return DRVMGR_OK;
}
#ifdef GPTIMER_INFO_AVAIL
static int gptimer_info(
struct drvmgr_dev *dev,
void (*print_line)(void *p, char *str),
void *p, int argc, char *argv[])
{
struct gptimer_priv *priv = dev->priv;
struct gptimer_timer *timer;
char buf[64];
int i;
if (priv == NULL || argc != 0)
return -DRVMGR_EINVAL;
sprintf(buf, "Timer Count: %d", priv->timer_cnt);
print_line(p, buf);
sprintf(buf, "REGS: 0x%08x", (unsigned int)priv->regs);
print_line(p, buf);
sprintf(buf, "BASE SCALER: %d", priv->regs->scaler_reload);
print_line(p, buf);
sprintf(buf, "BASE FREQ: %dkHz", priv->base_freq / 1000);
print_line(p, buf);
sprintf(buf, "SeparateIRQ: %s", priv->separate_interrupt ? "YES":"NO");
print_line(p, buf);
for (i=0; i<priv->timer_cnt; i++) {
timer = &priv->timers[i];
sprintf(buf, " - TIMER HW Index %d -", timer->tindex);
print_line(p, buf);
sprintf(buf, " TLIB Index: %d", timer->index);
print_line(p, buf);
sprintf(buf, " RELOAD REG: %d", timer->tregs->reload);
print_line(p, buf);
sprintf(buf, " CTRL REG: %d", timer->tregs->ctrl);
print_line(p, buf);
}
return DRVMGR_OK;
}
#endif
static inline struct gptimer_priv *priv_from_timer(struct gptimer_timer *t)
{
return (struct gptimer_priv *)
((unsigned int)t -
sizeof(struct gptimer_priv) -
t->index * sizeof(struct gptimer_timer));
}
static int gptimer_tlib_int_pend(struct tlib_dev *hand, int ack)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
unsigned int ctrl = timer->tregs->ctrl;
if ((ctrl & (GPTIMER_CTRL_IP | GPTIMER_CTRL_IE)) ==
(GPTIMER_CTRL_IP | GPTIMER_CTRL_IE)) {
/* clear Pending IRQ ? */
if (ack)
timer->tregs->ctrl = ctrl & timer->irq_ack_mask;
return 1; /* timer generated IRQ */
} else
return 0; /* was not timer causing IRQ */
}
void gptimer_isr(void *data)
{
struct gptimer_priv *priv = data;
int i;
/* Check all timers for IRQ */
for (i=0;i<priv->timer_cnt; i++) {
if (gptimer_tlib_int_pend((void *)&priv->timers[i], 0)) {
/* IRQ Was generated by Timer and Pending flag has *not*
* yet been cleared, this is to allow ISR to look at
* pending bit. Call ISR registered. Clear pending bit.
*/
if (priv->timers[i].tdev.isr_func) {
priv->timers[i].tdev.isr_func(
priv->timers[i].tdev.isr_data);
}
gptimer_tlib_int_pend((void *)&priv->timers[i], 1);
}
}
}
static void gptimer_tlib_reset(struct tlib_dev *hand)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
timer->tregs->ctrl = (timer->tregs->ctrl & timer->irq_ack_mask) &
GPTIMER_CTRL_IP;
timer->tregs->reload = 0xffffffff;
timer->tregs->ctrl = GPTIMER_CTRL_LD;
}
static void gptimer_tlib_get_freq(
struct tlib_dev *hand,
unsigned int *basefreq,
unsigned int *tickrate)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
struct gptimer_priv *priv = priv_from_timer(timer);
/* Calculate base frequency from Timer Clock and Prescaler */
if ( basefreq )
*basefreq = priv->base_freq;
if ( tickrate )
*tickrate = timer->tregs->reload + 1;
}
static int gptimer_tlib_set_freq(struct tlib_dev *hand, unsigned int tickrate)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
timer->tregs->reload = tickrate - 1;
/*Check that value was allowed (Timer may not be as wide as expected)*/
if ( timer->tregs->reload != (tickrate - 1) )
return -1;
else
return 0;
}
static void gptimer_tlib_irq_reg(struct tlib_dev *hand, tlib_isr_t func, void *data, int flags)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
struct gptimer_priv *priv = priv_from_timer(timer);
if ( priv->separate_interrupt ) {
drvmgr_interrupt_register(priv->dev, timer->tindex,
"gptimer", func, data);
} else {
if (priv->isr_installed == 0) {
/* Shared IRQ handler */
drvmgr_interrupt_register(
priv->dev,
0,
"gptimer_shared",
gptimer_isr,
priv);
}
priv->isr_installed++;
}
#if RTEMS_SMP
if (flags & TLIB_FLAGS_BROADCAST) {
int tindex = 0;
if (priv->separate_interrupt) {
/* Offset interrupt number with HW subtimer index */
tindex = timer->tindex;
}
drvmgr_interrupt_set_affinity(priv->dev, tindex,
_SMP_Get_online_processors());
}
#endif
timer->tregs->ctrl |= GPTIMER_CTRL_IE;
}
static void gptimer_tlib_irq_unreg(struct tlib_dev *hand, tlib_isr_t func, void *data)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
struct gptimer_priv *priv = priv_from_timer(timer);
/* Turn off IRQ at source, unregister IRQ handler */
timer->tregs->ctrl &= ~GPTIMER_CTRL_IE;
if ( priv->separate_interrupt ) {
drvmgr_interrupt_unregister(priv->dev, timer->tindex,
func, data);
} else {
timer->tdev.isr_func = NULL;
priv->isr_installed--;
if (priv->isr_installed == 0) {
drvmgr_interrupt_unregister(priv->dev, 0,
gptimer_isr, priv);
}
}
}
static void gptimer_tlib_start(struct tlib_dev *hand, int once)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
unsigned int ctrl;
/* Load the selected frequency before starting Frequency */
ctrl = GPTIMER_CTRL_LD | GPTIMER_CTRL_EN;
if ( once == 0 )
ctrl |= GPTIMER_CTRL_RS; /* Restart Timer */
timer->tregs->ctrl = ctrl | (timer->tregs->ctrl & timer->irq_ack_mask &
~GPTIMER_CTRL_RS);
}
static void gptimer_tlib_stop(struct tlib_dev *hand)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
/* Load the selected Frequency */
timer->tregs->ctrl &= ~(GPTIMER_CTRL_EN|GPTIMER_CTRL_IP);
}
static void gptimer_tlib_restart(struct tlib_dev *hand)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
timer->tregs->ctrl |= GPTIMER_CTRL_LD | GPTIMER_CTRL_EN;
}
static void gptimer_tlib_get_counter(
struct tlib_dev *hand,
unsigned int *counter)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
*counter = timer->tregs->value;
}
static void gptimer_tlib_get_widthmask(
struct tlib_dev *hand,
unsigned int *widthmask)
{
struct gptimer_timer *timer = (struct gptimer_timer *)hand;
struct gptimer_priv *priv = priv_from_timer(timer);
*widthmask = priv->widthmask;
}
static struct tlib_drv gptimer_tlib_drv =
{
.reset = gptimer_tlib_reset,
.get_freq = gptimer_tlib_get_freq,
.set_freq = gptimer_tlib_set_freq,
.irq_reg = gptimer_tlib_irq_reg,
.irq_unreg = gptimer_tlib_irq_unreg,
.start = gptimer_tlib_start,
.stop = gptimer_tlib_stop,
.restart = gptimer_tlib_restart,
.get_counter = gptimer_tlib_get_counter,
.custom = NULL,
.int_pend = gptimer_tlib_int_pend,
.get_widthmask = gptimer_tlib_get_widthmask,
};

View File

@@ -1,77 +0,0 @@
/*
* Timer Library (TLIB)
*
* COPYRIGHT (c) 2011.
* Cobham Gaisler AB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems.h>
#include <bsp/tlib.h>
struct tlib_dev *tlib_dev_head = NULL;
struct tlib_dev *tlib_dev_tail = NULL;
static int tlib_dev_cnt = 0;
/* Register Timer device to Timer Library */
int tlib_dev_reg(struct tlib_dev *newdev)
{
/* Reset device */
newdev->status = 0;
newdev->isr_func = NULL;
newdev->index = tlib_dev_cnt;
/* Insert last in queue */
newdev->next = NULL;
if ( tlib_dev_tail == NULL ) {
tlib_dev_head = newdev;
} else {
tlib_dev_tail->next = newdev;
}
tlib_dev_tail = newdev;
/* Return Index of Registered Timer */
return tlib_dev_cnt++;
}
void *tlib_open(int timer_no)
{
struct tlib_dev *dev;
if ( timer_no < 0 )
return NULL;
dev = tlib_dev_head;
while ( (timer_no > 0) && dev ) {
timer_no--;
dev = dev->next;
}
if ( dev ) {
if ( dev->status )
return NULL;
dev->status = 1;
/* Reset Timer to initial state */
tlib_reset(dev);
}
return dev;
}
void tlib_close(void *hand)
{
struct tlib_dev *dev = hand;
/* Stop any ongoing timer operation and unregister IRQ if registered */
tlib_stop(dev);
tlib_irq_unregister(dev);
/* Mark not open */
dev->status = 0;
}
int tlib_ntimer(void)
{
return tlib_dev_cnt;
}

View File

@@ -1,453 +0,0 @@
/*
* Clock Tick Device Driver using Timer Library implemented
* by the GRLIB GPTIMER / LEON2 Timer drivers.
*
* COPYRIGHT (c) 2010 - 2017.
* Cobham Gaisler AB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
*/
/*
* This is an implementation of the RTEMS "clockdrv_shell" interface for
* LEON2/3/4 systems using the Driver Manager. It is clock hardware agnostic
* and compatible with SMP and UP. Availability of free running counters is
* probed and selected as needed.
*/
#include <rtems.h>
#include <rtems/timecounter.h>
#include <rtems/clockdrv.h>
#include <stdlib.h>
#include <bsp.h>
#include <bsp/tlib.h>
#ifdef RTEMS_DRVMGR_STARTUP
#if defined(LEON3)
#include <leon.h>
#endif
struct ops {
/*
* Set up the free running counter using the Timecounter or Simple
* Timecounter interface.
*/
rtems_device_driver (*initialize_counter)(void);
/*
* Hardware-specific support at tick interrupt which runs early in Clock_isr.
* It can for example be used to check if interrupt was actually caused by
* the timer hardware. If return value is not RTEMS_SUCCESSFUL then Clock_isr
* returns immediately. at_tick can be initialized with NULL.
*/
rtems_device_driver (*at_tick)(void);
/*
* Typically calls rtems_timecounter_tick(). A specialized clock driver may
* use for example rtems_timecounter_tick_simple() instead.
*/
void (*timecounter_tick)(void);
/*
* Called when the clock driver exits. It can be used to stop functionality
* started by initialize_counter. The tick timer is stopped by default.
* shutdown_hardware can be initialized with NULL
*/
void (*shutdown_hardware)(void);
};
/*
* Different implementation depending on available free running counter for the
* timecounter.
*
* NOTE: The clock interface is not compatible with shared interrupts on the
* clock (tick) timer in SMP configuration.
*/
/* "simple timecounter" interface. Only for non-SMP. */
static const struct ops ops_simple;
/* Hardware support up-counter using LEON3 %asr23. */
static const struct ops ops_timetag;
/* Timestamp counter available in some IRQ(A)MP instantiations. */
static const struct ops ops_irqamp;
/* Separate GPTIMER subtimer as timecounter */
static const struct ops ops_subtimer;
struct clock_priv {
const struct ops *ops;
/*
* Timer number in Timer Library for tick timer used by this interface.
* Defaults to the first Timer in the System.
*/
int tlib_tick_index;
/* Timer number for timecounter timer if separate GPTIMER subtimer is used */
int tlib_counter_index;
void *tlib_tick;
void *tlib_counter;
rtems_timecounter_simple tc_simple;
struct timecounter tc;
};
static struct clock_priv priv;
/** Common interface **/
/* Set system clock timer instance */
void Clock_timer_register(int timer_number)
{
priv.tlib_tick_index = timer_number;
priv.tlib_counter_index = timer_number + 1;
}
static rtems_device_driver tlib_clock_find_timer(void)
{
/* Take Timer that should be used as system timer. */
priv.tlib_tick = tlib_open(priv.tlib_tick_index);
if (priv.tlib_tick == NULL) {
/* System Clock Timer not found */
return RTEMS_NOT_DEFINED;
}
/* Select which operation set to use */
#ifndef RTEMS_SMP
priv.ops = &ops_simple;
#else
/* When on LEON3 try to use dedicated hardware free running counter. */
leon3_up_counter_enable();
if (leon3_up_counter_is_available()) {
priv.ops = &ops_timetag;
return RTEMS_SUCCESSFUL;
} else {
volatile struct irqmp_timestamp_regs *irqmp_ts;
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
if (leon3_irqmp_has_timestamp(irqmp_ts)) {
priv.ops = &ops_irqamp;
return RTEMS_SUCCESSFUL;
}
}
/* Take another subtimer as the final option. */
priv.ops = &ops_subtimer;
#endif
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver tlib_clock_initialize_hardware(void)
{
/* Set tick rate in number of "Base-Frequency ticks" */
tlib_set_freq(priv.tlib_tick, rtems_configuration_get_microseconds_per_tick());
priv.ops->initialize_counter();
tlib_start(priv.tlib_tick, 0);
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver tlib_clock_at_tick(void)
{
if (priv.ops->at_tick) {
return priv.ops->at_tick();
}
return RTEMS_SUCCESSFUL;
}
static void tlib_clock_timecounter_tick(void)
{
priv.ops->timecounter_tick();
}
/* Return a value not equal to RTEMS_SUCCESFUL to make Clock_initialize fail. */
static rtems_device_driver tlib_clock_install_isr(rtems_isr *isr)
{
int flags = 0;
#ifdef RTEMS_SMP
/* We shall broadcast the clock interrupt to all processors. */
flags = TLIB_FLAGS_BROADCAST;
#endif
tlib_irq_register(priv.tlib_tick, isr, NULL, flags);
return RTEMS_SUCCESSFUL;
}
static void tlib_clock_shutdown_hardware(void)
{
if (priv.tlib_tick) {
tlib_stop(priv.tlib_tick);
priv.tlib_tick = NULL;
}
if (priv.ops->shutdown_hardware) {
priv.ops->shutdown_hardware();
}
}
/** Simple counter **/
static uint32_t simple_tlib_tc_get(rtems_timecounter_simple *tc)
{
unsigned int clicks = 0;
if (priv.tlib_tick != NULL) {
tlib_get_counter(priv.tlib_tick, &clicks);
}
return clicks;
}
static bool simple_tlib_tc_is_pending(rtems_timecounter_simple *tc)
{
bool pending = false;
if (priv.tlib_tick != NULL) {
pending = tlib_interrupt_pending(priv.tlib_tick, 0) != 0;
}
return pending;
}
static uint32_t simple_tlib_tc_get_timecount(struct timecounter *tc)
{
return rtems_timecounter_simple_downcounter_get(
tc,
simple_tlib_tc_get,
simple_tlib_tc_is_pending
);
}
static rtems_device_driver simple_initialize_counter(void)
{
uint64_t frequency;
unsigned int tick_hz;
frequency = 1000000;
tick_hz = rtems_configuration_get_microseconds_per_tick();
rtems_timecounter_simple_install(
&priv.tc_simple,
frequency,
tick_hz,
simple_tlib_tc_get_timecount
);
return RTEMS_NOT_DEFINED;
}
static void simple_tlib_tc_at_tick(rtems_timecounter_simple *tc)
{
/* Nothing to do */
}
/*
* Support for shared interrupts. Ack IRQ at source, only handle interrupts
* generated from the tick-timer. This is called early in Clock_isr.
*/
static rtems_device_driver simple_at_tick(void)
{
if (tlib_interrupt_pending(priv.tlib_tick, 1) == 0) {
return RTEMS_NOT_DEFINED;
}
return RTEMS_SUCCESSFUL;
}
static void simple_timecounter_tick(void)
{
rtems_timecounter_simple_downcounter_tick(
&priv.tc_simple,
simple_tlib_tc_get,
simple_tlib_tc_at_tick
);
}
static const struct ops ops_simple = {
.initialize_counter = simple_initialize_counter,
.at_tick = simple_at_tick,
.timecounter_tick = simple_timecounter_tick,
.shutdown_hardware = NULL,
};
/** Subtimer as counter **/
static uint32_t subtimer_get_timecount(struct timecounter *tc)
{
unsigned int counter;
tlib_get_counter(priv.tlib_counter, &counter);
return 0xffffffff - counter;
}
static rtems_device_driver subtimer_initialize_counter(void)
{
unsigned int mask;
unsigned int basefreq;
if (priv.tlib_counter_index == priv.tlib_tick_index) {
priv.tlib_counter_index = priv.tlib_tick_index + 1;
}
/* Take Timer that should be used as timecounter upcounter timer. */
priv.tlib_counter = tlib_open(priv.tlib_counter_index);
if (priv.tlib_counter == NULL) {
/* Timecounter timer not found */
return RTEMS_NOT_DEFINED;
}
/* Configure free running counter: GPTIMER */
tlib_get_freq(priv.tlib_counter, &basefreq, NULL);
tlib_get_widthmask(priv.tlib_counter, &mask);
priv.tc.tc_get_timecount = subtimer_get_timecount;
priv.tc.tc_counter_mask = mask;
priv.tc.tc_frequency = basefreq;
priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install(&priv.tc);
/* Start free running counter */
tlib_start(priv.tlib_counter, 0);
return RTEMS_SUCCESSFUL;
}
static void subtimer_timecounter_tick(void)
{
rtems_timecounter_tick();
}
static void subtimer_shutdown_hardware(void)
{
if (priv.tlib_counter) {
tlib_stop(priv.tlib_counter);
priv.tlib_counter = NULL;
}
}
static const struct ops ops_subtimer = {
.initialize_counter = subtimer_initialize_counter,
.timecounter_tick = subtimer_timecounter_tick,
.shutdown_hardware = subtimer_shutdown_hardware,
};
#if defined(LEON3)
/** DSU timetag as counter **/
static uint32_t timetag_get_timecount(struct timecounter *tc)
{
return leon3_up_counter_low();
}
static rtems_device_driver timetag_initialize_counter(void)
{
/* Configure free running counter: timetag */
priv.tc.tc_get_timecount = timetag_get_timecount;
priv.tc.tc_counter_mask = 0xffffffff;
priv.tc.tc_frequency = leon3_up_counter_frequency();
priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install(&priv.tc);
return RTEMS_SUCCESSFUL;
}
static void timetag_timecounter_tick(void)
{
rtems_timecounter_tick();
}
static const struct ops ops_timetag = {
.initialize_counter = timetag_initialize_counter,
.at_tick = NULL,
.timecounter_tick = timetag_timecounter_tick,
.shutdown_hardware = NULL,
};
#endif
#if defined(LEON3)
/** IRQ(A)MP timestamp as counter **/
static uint32_t irqamp_get_timecount(struct timecounter *tc)
{
return LEON3_IrqCtrl_Regs->timestamp[0].counter;
}
static rtems_device_driver irqamp_initialize_counter(void)
{
volatile struct irqmp_timestamp_regs *irqmp_ts;
static const uint32_t A_TSISEL_FIELD = 0xf;
/* Configure free running counter: timetag */
priv.tc.tc_get_timecount = irqamp_get_timecount;
priv.tc.tc_counter_mask = 0xffffffff;
priv.tc.tc_frequency = leon3_up_counter_frequency();
priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install(&priv.tc);
/*
* The counter increments whenever a TSISEL field in a Timestamp Control
* Register is non-zero.
*/
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
irqmp_ts->control = A_TSISEL_FIELD;
return RTEMS_SUCCESSFUL;
}
static void irqamp_timecounter_tick(void)
{
rtems_timecounter_tick();
}
static const struct ops ops_irqamp = {
.initialize_counter = irqamp_initialize_counter,
.at_tick = NULL,
.timecounter_tick = irqamp_timecounter_tick,
.shutdown_hardware = NULL,
};
#endif
/** Interface to the Clock Driver Shell (dev/clock/clockimpl.h) **/
#define Clock_driver_support_find_timer() \
do { \
rtems_device_driver ret; \
ret = tlib_clock_find_timer(); \
if (RTEMS_SUCCESSFUL != ret) { \
return ret; \
} \
} while (0)
#define Clock_driver_support_install_isr( isr ) \
do { \
rtems_device_driver ret; \
ret = tlib_clock_install_isr( isr ); \
if (RTEMS_SUCCESSFUL != ret) { \
return ret; \
} \
} while (0)
#define Clock_driver_support_set_interrupt_affinity(online_processors) \
/* Done by tlib_clock_install_isr() */
#define Clock_driver_support_initialize_hardware() \
do { \
rtems_device_driver ret; \
ret = tlib_clock_initialize_hardware(); \
if (RTEMS_SUCCESSFUL != ret) { \
return ret; \
} \
} while (0)
#define Clock_driver_support_shutdown_hardware() \
tlib_clock_shutdown_hardware()
#define Clock_driver_timecounter_tick() \
tlib_clock_timecounter_tick()
#define Clock_driver_support_at_tick() \
do { \
rtems_device_driver ret; \
ret = tlib_clock_at_tick(); \
if (RTEMS_SUCCESSFUL != ret) { \
return; \
} \
} while (0)
#include "../../../shared/dev/clock/clockimpl.h"
#endif /* RTEMS_DRVMGR_STARTUP */