diff options
author | Alexander Krutwig <alexander.krutwig@embedded-brains.de> | 2015-04-01 15:33:25 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-05-20 08:40:34 +0200 |
commit | 75acd9e69f906cbd880a17ee4ca705ad7caa92c0 (patch) | |
tree | 71529028154cb323286b02392def2e5277eed312 /c/src/lib/libbsp/i386/pc386/clock | |
parent | timecounter: Use in RTEMS (diff) | |
download | rtems-75acd9e69f906cbd880a17ee4ca705ad7caa92c0.tar.bz2 |
bsps: Convert clock drivers to use a timecounter
Update #2271.
Diffstat (limited to 'c/src/lib/libbsp/i386/pc386/clock')
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/clock/ckinit.c | 125 |
1 files changed, 22 insertions, 103 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c index 2782252680..44a35bc6c1 100644 --- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c @@ -28,6 +28,7 @@ #include <bspopts.h> #include <libcpu/cpuModel.h> #include <assert.h> +#include <rtems/timecounter.h> #define CLOCK_VECTOR 0 @@ -39,29 +40,24 @@ uint32_t pc386_clock_click_count; void Clock_isr(void *param); static void Clock_driver_support_at_tick_empty(void); static void clockOff(void); -static void Clock_driver_support_at_tick_tsc(void); -static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void); -static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void); static void Clock_isr_handler(void *param); /* - * Roughly the number of cycles per tick and per nanosecond. Note that these + * Roughly the number of cycles per second. Note that these * will be wildly inaccurate if the chip speed changes due to power saving * or thermal modes. * * NOTE: These are only used when the TSC method is used. */ -uint64_t pc586_tsc_per_tick; -uint64_t pc586_nanoseconds_per_tick; +static uint64_t pc586_tsc_frequency; -uint64_t pc586_tsc_at_tick; +static struct timecounter pc386_tc; /* this driver may need to count ISRs per tick */ #define CLOCK_DRIVER_ISRS_PER_TICK 1 #define CLOCK_DRIVER_ISRS_PER_TICK_VALUE pc386_isrs_per_tick -/* The driver uses the count in Clock_driver_support_at_tick */ -extern volatile uint32_t Clock_driver_isrs; +extern volatile uint32_t Clock_driver_ticks; #define READ_8254( _lsb, _msb ) \ do { outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH); \ @@ -74,60 +70,21 @@ extern volatile uint32_t Clock_driver_isrs; * Hooks which get swapped based upon which nanoseconds since last * tick method is preferred. */ -void (*Clock_driver_support_at_tick)(void) = NULL; -uint32_t (*Clock_driver_nanoseconds_since_last_tick)(void) = NULL; - -/* - * What do we do at each clock tick? - */ -static void Clock_driver_support_at_tick_tsc(void) -{ - pc586_tsc_at_tick = rdtsc(); -} - -static void Clock_driver_support_at_tick_empty(void) -{ -} +#define Clock_driver_support_at_tick() #define Clock_driver_support_install_isr( _new, _old ) \ do { \ _old = NULL; \ } while(0) -/* - * Get nanoseconds using Pentium-compatible TSC register - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void) +static uint32_t pc386_get_timecount_tsc(struct timecounter *tc) { - uint64_t diff_nsec; - - diff_nsec = rdtsc() - pc586_tsc_at_tick; - - /* - * At this point, with a hypothetical 10 GHz CPU clock and 100 Hz tick - * clock, diff_nsec <= 27 bits. - */ - diff_nsec *= pc586_nanoseconds_per_tick; /* <= 54 bits */ - diff_nsec /= pc586_tsc_per_tick; - - if (diff_nsec > pc586_nanoseconds_per_tick) - /* - * Hmmm... Some drift or rounding. Pin the value to 1 nanosecond before - * the next tick. - */ - /* diff_nsec = pc586_nanoseconds_per_tick - 1; */ - diff_nsec = 12345; - - return (uint32_t)diff_nsec; + return (uint32_t)rdtsc(); } -/* - * Get nanoseconds using 8254 timer chip - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void) +static uint32_t pc386_get_timecount_i8254(struct timecounter *tc) { - uint32_t usecs, clicks, isrs; - uint32_t usecs1, usecs2; + uint32_t irqs; uint8_t lsb, msb; rtems_interrupt_level level; @@ -136,34 +93,10 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void) */ rtems_interrupt_disable(level); READ_8254(lsb, msb); - isrs = Clock_driver_isrs; + irqs = Clock_driver_ticks; rtems_interrupt_enable(level); - /* - * Now do the math - */ - /* convert values read into counter clicks */ - clicks = ((msb << 8) | lsb); - - /* whole ISRs we have done since the last tick */ - usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr; - - /* the partial ISR we in the middle of now */ - usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks); - - /* total microseconds */ - usecs = usecs1 + usecs2; - #if 0 - printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 ); - printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n", - pc386_clock_click_count, clicks, - Clock_driver_isrs, pc386_isrs_per_tick, - pc386_microseconds_per_isr, usecs ); - #endif - - /* return it in nanoseconds */ - return usecs * 1000; - + return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb); } /* @@ -175,9 +108,6 @@ static void calibrate_tsc(void) uint8_t then_lsb, then_msb, now_lsb, now_msb; uint32_t i; - pc586_nanoseconds_per_tick = - rtems_configuration_get_microseconds_per_tick() * 1000; - /* * We just reset the timer, so we know we're at the beginning of a tick. */ @@ -204,16 +134,11 @@ static void calibrate_tsc(void) } while (1); } - pc586_tsc_per_tick = rdtsc() - begin_time; - - /* Initialize "previous tick" counters */ - pc586_tsc_at_tick = rdtsc(); + pc586_tsc_frequency = rdtsc() - begin_time; #if 0 - printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_per_tick / 1000000)); + printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_frequency / 1000000)); #endif - - pc586_tsc_per_tick /= rtems_clock_get_ticks_per_second(); } static void clockOn(void) @@ -299,24 +224,18 @@ void Clock_driver_support_initialize_hardware(void) if ( use_8254 ) { /* printk( "Use 8254\n" ); */ - Clock_driver_support_at_tick = Clock_driver_support_at_tick_empty; - Clock_driver_nanoseconds_since_last_tick = - bsp_clock_nanoseconds_since_last_tick_i8254; + pc386_tc.tc_get_timecount = pc386_get_timecount_i8254; + pc386_tc.tc_counter_mask = 0xffffffff; + pc386_tc.tc_frequency = TIMER_TICK; } else { /* printk( "Use TSC\n" ); */ - Clock_driver_support_at_tick = Clock_driver_support_at_tick_tsc; - Clock_driver_nanoseconds_since_last_tick = - bsp_clock_nanoseconds_since_last_tick_tsc; + pc386_tc.tc_get_timecount = pc386_get_timecount_tsc; + pc386_tc.tc_counter_mask = 0xffffffff; + pc386_tc.tc_frequency = pc586_tsc_frequency; } - /* Shell installs nanosecond handler before calling - * Clock_driver_support_initialize_hardware() :-( - * so we do it again now that we're ready. - */ - rtems_clock_set_nanoseconds_extension( - Clock_driver_nanoseconds_since_last_tick - ); - + pc386_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&pc386_tc); Clock_isr_enabled = true; } |