forked from Imagelibrary/rtems
bsps: Move benchmark timer to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 = ®s->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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user