Use new timer API and use usec timer instead of cycles timer

This commit is contained in:
Stefan Hepp
2014-03-18 14:05:41 +01:00
parent 4626a8b696
commit 1c1b68be2f
3 changed files with 34 additions and 57 deletions

View File

@@ -22,6 +22,10 @@
#include <rtems.h> #include <rtems.h>
#include <bsp.h> #include <bsp.h>
#include <machine/patmos.h>
#include <machine/exceptions.h>
#include <machine/rtc.h>
void Clock_exit( void ); void Clock_exit( void );
rtems_isr Clock_isr( rtems_vector_number vector )__attribute__((naked)); rtems_isr Clock_isr( rtems_vector_number vector )__attribute__((naked));
@@ -52,6 +56,8 @@ rtems_device_minor_number rtems_clock_minor;
uint64_t cycles_offset; uint64_t cycles_offset;
/* CPU frequency in MHZ */ /* CPU frequency in MHZ */
uint32_t freq; uint32_t freq;
/* timestamp of the last tick in usec */
uint64_t usec_offset;
/* /*
* The previous ISR on this clock tick interrupt vector. * The previous ISR on this clock tick interrupt vector.
@@ -61,41 +67,15 @@ rtems_isr_entry Old_ticker;
void Clock_exit( void ); void Clock_exit( void );
void set_cpu_cycles (uint64_t time_warp) void set_usec_timer (uint64_t time_warp)
{ {
__PATMOS_RTC_WR_CYCLE_LOW((unsigned int)time_warp); // __PATMOS_RTC_WR_CYCLE_LOW((unsigned int)time_warp);
__PATMOS_RTC_WR_CYCLE_UP((unsigned int)(time_warp >> 32)); // __PATMOS_RTC_WR_CYCLE_UP((unsigned int)(time_warp >> 32));
} usec_offset += time_warp;
uint64_t get_cpu_cycles(void) arm_usec_timer(usec_offset);
{
uint32_t u;
uint32_t l;
__PATMOS_RTC_RD_CYCLE_LOW(l);
__PATMOS_RTC_RD_CYCLE_UP(u);
return (((uint64_t)u) << 32) | l;
}
uint64_t get_cpu_time(void)
{
uint32_t u;
uint32_t l;
__PATMOS_RTC_RD_TIME_LOW(l);
__PATMOS_RTC_RD_TIME_UP(u);
return (((uint64_t)u) << 32) | l;
}
uint32_t get_cpu_freq(void)
{
uint32_t freq;
__PATMOS_CPU_RD_FREQ(freq);
return freq;
} }
uint32_t get_cpu_freq_mhz(void) uint32_t get_cpu_freq_mhz(void)
@@ -232,7 +212,7 @@ rtems_isr Clock_isr(
"i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s9_OFFSET), "i" (s10_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s9_OFFSET), "i" (s10_OFFSET),
"i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET), "i" (s15_OFFSET)); "i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET), "i" (s15_OFFSET));
__PATMOS_RTC_WR_INTERVAL(rtems_configuration_get_microseconds_per_tick() * freq); set_usec_timer(rtems_configuration_get_microseconds_per_tick());
/* /*
* Accurate count of ISRs * Accurate count of ISRs
@@ -344,7 +324,13 @@ void Install_clock(
Clock_driver_ticks = 0; Clock_driver_ticks = 0;
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000; Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
__PATMOS_RTC_WR_ISR((uint32_t)clock_isr); exc_register(EXC_INTR_USEC, (uint32_t)clock_isr);
// clear pending flags
intr_clear_all_pending();
// unmask interrupt
intr_unmask(EXC_INTR_USEC);
// enable interrupts
intr_enable();
#if defined(Clock_driver_nanoseconds_since_last_tick) #if defined(Clock_driver_nanoseconds_since_last_tick)
rtems_clock_set_nanoseconds_extension( rtems_clock_set_nanoseconds_extension(
@@ -359,7 +345,11 @@ void Install_clock(
*/ */
cycles_offset = get_cpu_cycles(); cycles_offset = get_cpu_cycles();
__PATMOS_RTC_WR_INTERVAL(rtems_configuration_get_microseconds_per_tick() * freq); usec_offset = get_cpu_usecs();
set_usec_timer(rtems_configuration_get_microseconds_per_tick());
/* /*
* Schedule the clock cleanup routine to execute if the application exits. * Schedule the clock cleanup routine to execute if the application exits.

View File

@@ -42,8 +42,6 @@ typedef _IODEV unsigned int volatile * const _iodev_ptr_t;
extern char _cpuinfo_base; /* linker symbol giving the address of the CPU info */ extern char _cpuinfo_base; /* linker symbol giving the address of the CPU info */
extern uint32_t get_cpu_freq(void);
extern uint32_t get_cpu_freq_mhz(void); extern uint32_t get_cpu_freq_mhz(void);
#define __PATMOS_INF 0xFFFFFFFF /* maximum cycles the clock can run without interrupts */ #define __PATMOS_INF 0xFFFFFFFF /* maximum cycles the clock can run without interrupts */
@@ -120,11 +118,7 @@ extern char _uart_base; /* linker symbol giving the address of the UART */
extern char _timer_base; /* linker symbol giving the address of the RTC */ extern char _timer_base; /* linker symbol giving the address of the RTC */
extern void set_cpu_cycles (uint64_t time_warp); extern void set_usec_timer (uint64_t time_warp);
extern uint64_t get_cpu_cycles(void);
extern uint64_t get_cpu_time(void);
/* Address to access the cycle counter low register of the RTC */ /* Address to access the cycle counter low register of the RTC */
#define __PATMOS_RTC_CYCLE_LOW_ADDR (&_timer_base + 0x04) #define __PATMOS_RTC_CYCLE_LOW_ADDR (&_timer_base + 0x04)
@@ -138,11 +132,8 @@ extern uint64_t get_cpu_time(void);
/* Address to access the time in microseconds up register of the RTC */ /* Address to access the time in microseconds up register of the RTC */
#define __PATMOS_RTC_TIME_UP_ADDR (&_timer_base + 0x08) #define __PATMOS_RTC_TIME_UP_ADDR (&_timer_base + 0x08)
/* Address to access the interrupt interval register of the RTC */ /* Address to access the ISR address register of the RTC cycle timer */
#define __PATMOS_RTC_INTERVAL_ADDR (&_timer_base + 0x10) #define __PATMOS_RTC_ISR_ADDR (&_excunit_base + 0xc0)
/* Address to access the ISR address register of the RTC */
#define __PATMOS_RTC_ISR_ADDR (&_timer_base + 0x14)
/* Macro to read the RTC's cycle counter low register of the RTC */ /* Macro to read the RTC's cycle counter low register of the RTC */
#define __PATMOS_RTC_RD_CYCLE_LOW(res) res = *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR); #define __PATMOS_RTC_RD_CYCLE_LOW(res) res = *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR);
@@ -156,18 +147,12 @@ extern uint64_t get_cpu_time(void);
/* Macro to read the RTC's time in microseconds up register of the RTC */ /* Macro to read the RTC's time in microseconds up register of the RTC */
#define __PATMOS_RTC_RD_TIME_UP(res) res = *((_iodev_ptr_t)__PATMOS_RTC_TIME_UP_ADDR); #define __PATMOS_RTC_RD_TIME_UP(res) res = *((_iodev_ptr_t)__PATMOS_RTC_TIME_UP_ADDR);
/* Macro to read the RTC's interrupt interval register */
#define __PATMOS_RTC_RD_INTERVAL(interval) interval = *((_iodev_ptr_t)__PATMOS_RTC_INTERVAL_ADDR);
/* Macro to write the RTC's cycle counter low register */ /* Macro to write the RTC's cycle counter low register */
#define __PATMOS_RTC_WR_CYCLE_LOW(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR) = val; #define __PATMOS_RTC_WR_CYCLE_LOW(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR) = val;
/* Macro to write the RTC's cycle counter up register */ /* Macro to write the RTC's cycle counter up register */
#define __PATMOS_RTC_WR_CYCLE_UP(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_UP_ADDR) = val; #define __PATMOS_RTC_WR_CYCLE_UP(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_UP_ADDR) = val;
/* Macro to write the RTC's interrupt interval register */
#define __PATMOS_RTC_WR_INTERVAL(interval) *((_iodev_ptr_t)__PATMOS_RTC_INTERVAL_ADDR) = interval;
/* Macro to write the RTC's ISR address register */ /* Macro to write the RTC's ISR address register */
#define __PATMOS_RTC_WR_ISR(address) *((_iodev_ptr_t)__PATMOS_RTC_ISR_ADDR) = address; #define __PATMOS_RTC_WR_ISR(address) *((_iodev_ptr_t)__PATMOS_RTC_ISR_ADDR) = address;

View File

@@ -18,31 +18,33 @@
#include <bsp.h> #include <bsp.h>
#include <machine/rtc.h>
bool benchmark_timer_find_average_overhead; bool benchmark_timer_find_average_overhead;
#define AVG_OVERHEAD 0 /* It typically takes 0 microseconds */ #define AVG_OVERHEAD 0 /* It typically takes 0 microseconds */
/* to start/stop the timer. */ /* to start/stop the timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this */ #define LEAST_VALID 1 /* Don't trust a value lower than this */
uint64_t timer_offset;
void benchmark_timer_initialize(void) void benchmark_timer_initialize(void)
{ {
/* /*
* Timer runs long and accurate enough not to require an interrupt. * Timer runs long and accurate enough not to require an interrupt.
*/ */
__PATMOS_RTC_WR_INTERVAL(__PATMOS_INF); timer_offset = get_cpu_cycles();
} }
int benchmark_timer_read(void) int benchmark_timer_read(void)
{ {
uint32_t total; uint64_t total;
/* /*
* Read the timer and see how many clicks it has been since we started. * Read the timer and see how many clicks it has been since we started.
*/ */
__PATMOS_RTC_RD_INTERVAL(total); total = (get_cpu_cycles() - timer_offset)/get_cpu_freq_mhz();
total = (__PATMOS_INF - total)/get_cpu_freq_mhz();
if ( benchmark_timer_find_average_overhead == true ) if ( benchmark_timer_find_average_overhead == true )
return total; /* in one microsecond units */ return total; /* in one microsecond units */