Changeset fb573a71 in rtems


Ignore:
Timestamp:
Oct 5, 2005, 2:39:35 AM (15 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Children:
e75e10d
Parents:
24b6d2f
Message:

2005-08-23 Karel Gardas <kgardas@…>>

  • timer/timer.c: Enhance to use either interupt-based timer functions on older CPUs or to use TSC-based timer functions on more recent (Pentium and above) CPUs. The decision is made in Timer_initialize function when it is called for the first time based on a result obtained from cpuid instruction during the BSP initialization phase. During the first call, there are also late bindings to the implementation functions initialized to appropriate values.
Location:
c/src/lib/libbsp/i386/pc386
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/ChangeLog

    r24b6d2f rfb573a71  
     12005-08-23  Karel Gardas  <kgardas@objectsecurity.com>>
     2
     3        * timer/timer.c: Enhance to use either interupt-based timer
     4        functions on older CPUs or to use TSC-based timer functions on
     5        more recent (Pentium and above) CPUs. The decision is made in
     6        Timer_initialize function when it is called for the first time
     7        based on a result obtained from cpuid instruction during the BSP
     8        initialization phase. During the first call, there are also late
     9        bindings to the implementation functions initialized to
     10        appropriate values.
     11
    1122005-09-29      Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
    213
  • c/src/lib/libbsp/i386/pc386/timer/timer.c

    r24b6d2f rfb573a71  
    3939+--------------------------------------------------------------------------*/
    4040
    41 
    4241#include <stdlib.h>
    4342
     
    5251#define SLOW_DOWN_IO  0x80      /* io which does nothing */
    5352
    54 #define TWO_MS  (rtems_unsigned32)(2000)     /* TWO_MS = 2000us (sic!) */
     53#define TWO_MS  (uint32_t)(2000)     /* TWO_MS = 2000us (sic!) */
    5554
    5655#define MSK_NULL_COUNT 0x40     /* bit counter available for reading */
     
    6059| Global Variables
    6160+--------------------------------------------------------------------------*/
    62 volatile rtems_unsigned32 Ttimer_val;
     61volatile uint32_t        Ttimer_val;
    6362rtems_boolean             Timer_driver_Find_average_overhead = TRUE;
    6463volatile unsigned int     fastLoop1ms, slowLoop1ms;
     64void (*Timer_initialize_function)(void) = 0;
     65uint32_t (*Read_timer_function)(void) = 0;
     66void (*Timer_exit_function)(void) = 0;
    6567
    6668/*-------------------------------------------------------------------------+
     
    6971extern void timerisr(void);
    7072       /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
     73extern int x86_capability;
     74
     75/*
     76 * forward declarations
     77 */
     78
     79void Timer_exit();
    7180
    7281/*-------------------------------------------------------------------------+
    7382| Pentium optimized timer handling.
    7483+--------------------------------------------------------------------------*/
    75 #if defined(pentium)
    7684
    7785/*-------------------------------------------------------------------------+
     
    8088| Global Variables: None.
    8189|        Arguments: None.
    82 |          Returns: Value of PENTIUM on-chip cycle counter. 
     90|          Returns: Value of PENTIUM on-chip cycle counter.
    8391+--------------------------------------------------------------------------*/
    8492static inline unsigned long long
     
    9199} /* rdtsc */
    92100
    93 
    94101/*-------------------------------------------------------------------------+
    95102|         Function: Timer_exit
     
    98105| Global Variables: None.
    99106|        Arguments: None.
    100 |          Returns: Nothing.
    101 +--------------------------------------------------------------------------*/
    102 void
    103 Timer_exit(void)
    104 {
    105 } /* Timer_exit */
    106 
     107|          Returns: Nothing.
     108+--------------------------------------------------------------------------*/
     109void
     110tsc_timer_exit(void)
     111{
     112} /* tsc_timer_exit */
    107113
    108114/*-------------------------------------------------------------------------+
     
    111117| Global Variables: Ttimer_val.
    112118|        Arguments: None.
    113 |          Returns: Nothing. 
    114 +--------------------------------------------------------------------------*/
    115 void
    116 Timer_initialize(void)
     119|          Returns: Nothing.
     120+--------------------------------------------------------------------------*/
     121void
     122tsc_timer_initialize(void)
    117123{
    118124  static rtems_boolean First = TRUE;
     
    125131  }
    126132  Ttimer_val = rdtsc(); /* read starting time */
    127 } /* Timer_initialize */
    128 
     133} /* tsc_timer_initialize */
    129134
    130135/*-------------------------------------------------------------------------+
     
    133138| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
    134139|        Arguments: None.
    135 |          Returns: Nothing. 
    136 +--------------------------------------------------------------------------*/
    137 rtems_unsigned32
    138 Read_timer(void)
    139 {
    140   register rtems_unsigned32 total;
    141 
    142   total =  (rtems_unsigned32)(rdtsc() - Ttimer_val);
     140|          Returns: Nothing.
     141+--------------------------------------------------------------------------*/
     142uint32_t
     143tsc_read_timer(void)
     144{
     145  register uint32_t        total;
     146
     147  total =  (uint32_t)(rdtsc() - Ttimer_val);
    143148
    144149  if (Timer_driver_Find_average_overhead)
     
    148153  else
    149154    return (total - AVG_OVERHEAD);
    150 } /* Read_timer */
    151 
    152 #else /* pentium */
     155} /* tsc_read_timer */
    153156
    154157/*-------------------------------------------------------------------------+
     
    156159+--------------------------------------------------------------------------*/
    157160#define US_PER_ISR   250  /* Number of micro-seconds per timer interruption */
    158 
    159161
    160162/*-------------------------------------------------------------------------+
     
    164166| Global Variables: None.
    165167|        Arguments: None.
    166 |          Returns: Nothing. 
     168|          Returns: Nothing.
    167169+--------------------------------------------------------------------------*/
    168170static void
     
    179181} /* Timer_exit */
    180182
    181 
    182 static void
     183static void
    183184timerOn(const rtems_raw_irq_connect_data* used)
    184185{
     
    193194}
    194195
    195 static int 
     196static int
    196197timerIsOn(const rtems_raw_irq_connect_data *used)
    197198{
    198      return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);}
     199     return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
     200}
    199201
    200202static rtems_raw_irq_connect_data timer_raw_irq_data = {
     
    212214| Global Variables: None.
    213215|        Arguments: None.
    214 |          Returns: Nothing. 
    215 +--------------------------------------------------------------------------*/
    216 void
    217 Timer_exit(void)
     216|          Returns: Nothing.
     217+--------------------------------------------------------------------------*/
     218void
     219i386_timer_exit(void)
    218220{
    219221  i386_delete_idt_entry (&timer_raw_irq_data);
     
    225227| Global Variables: Ttimer_val.
    226228|        Arguments: None.
    227 |          Returns: Nothing. 
    228 +--------------------------------------------------------------------------*/
    229 void
    230 Timer_initialize(void)
     229|          Returns: Nothing.
     230+--------------------------------------------------------------------------*/
     231void
     232i386_timer_initialize(void)
    231233{
    232234  static rtems_boolean First = TRUE;
     
    249251} /* Timer_initialize */
    250252
    251 
    252253/*-------------------------------------------------------------------------+
    253254|         Function: Read_timer
     
    255256| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
    256257|        Arguments: None.
    257 |          Returns: Nothing. 
    258 +--------------------------------------------------------------------------*/
    259 rtems_unsigned32
    260 Read_timer(void)
    261 {
    262   register rtems_unsigned32 total, clicks;
    263   register rtems_unsigned8  lsb, msb;
     258|          Returns: Nothing.
     259+--------------------------------------------------------------------------*/
     260uint32_t
     261i386_read_timer(void)
     262{
     263  register uint32_t        total, clicks;
     264  register uint8_t          lsb, msb;
    264265
    265266  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
     
    277278}
    278279
    279 #endif /* pentium */
    280 
     280/*
     281 * General timer functions using either TSC-based implementation
     282 * or interrupt-based implementation
     283 */
     284
     285void
     286Timer_initialize(void)
     287{
     288    static rtems_boolean First = TRUE;
     289
     290    if (First) {
     291        if (x86_capability & (1 << 4) ) {
     292#if defined(DEBUG)
     293            printk("TSC: timer initialization\n");
     294#endif
     295            Timer_initialize_function = &tsc_timer_initialize;
     296            Read_timer_function = &tsc_read_timer;
     297            Timer_exit_function = &tsc_timer_exit;
     298        }
     299        else {
     300#if defined(DEBUG)
     301            printk("ISR: timer initialization\n");
     302#endif
     303            Timer_initialize_function = &i386_timer_initialize;
     304            Read_timer_function = &i386_read_timer;
     305            Timer_exit_function = &i386_timer_exit;
     306        }
     307        First = FALSE;
     308    }
     309    (*Timer_initialize_function)();
     310}
     311
     312uint32_t
     313Read_timer()
     314{
     315    return (*Read_timer_function)();
     316}
     317
     318void
     319Timer_exit()
     320{
     321    return (*Timer_exit_function)();
     322}
    281323
    282324/*-------------------------------------------------------------------------+
     
    285327| Global Variables: None.
    286328|        Arguments: None.
    287 |          Returns: Nothing. 
     329|          Returns: Nothing.
    288330+--------------------------------------------------------------------------*/
    289331rtems_status_code Empty_function(void)
     
    291333  return RTEMS_SUCCESSFUL;
    292334} /* Empty function */
    293  
    294335
    295336/*-------------------------------------------------------------------------+
     
    298339| Global Variables: Timer_driver_Find_average_overhead.
    299340|        Arguments: find_flag - new value of the flag.
    300 |          Returns: Nothing. 
     341|          Returns: Nothing.
    301342+--------------------------------------------------------------------------*/
    302343void
     
    320361}
    321362
    322 
    323 /*-------------------------------------------------------------------------+
    324 | Description: Reads the current value of the timer, and converts the
    325 |                          number of ticks to micro-seconds.   
    326 | Returns: number of clock bits elapsed since last load.
     363/*-------------------------------------------------------------------------+
     364| Description: Reads the current value of the timer, and converts the
     365|                          number of ticks to micro-seconds.
     366| Returns: number of clock bits elapsed since last load.
    327367+--------------------------------------------------------------------------*/
    328368unsigned int readTimer0()
     
    339379  if (status & RB_OUTPUT )
    340380        count += lastLoadedValue;
    341  
     381
    342382  return (2*lastLoadedValue - count);
    343383}
     
    373413  unsigned int slowLoopGranularity, fastLoopGranularity;
    374414  rtems_interrupt_level  level;
    375  
     415
    376416#ifdef DEBUG_CALIBRATE
    377417  printk( "Calibrate_loop_1ms is starting,  please wait ( but not too loooong. )\n" );
    378 #endif 
     418#endif
    379419  targetClockBits = US_TO_TICK(1000);
    380  
     420
    381421  rtems_interrupt_disable(level);
    382422  /*
     
    385425  Timer0Reset();
    386426  readTimer0();
    387   /* 
     427  /*
    388428   * Compute the minimal offset to apply due to read counter register.
    389429   */
     
    438478  }
    439479  slowLoopGranularity = (res - offset - emptyCall)/ 10;
    440  
     480
    441481  if (slowLoopGranularity == 0) {
    442482    printk("Problem #3 in Calibrate_loop_1ms in file libbsp/i386/pc386/timer/timer.c\n");
     
    445485
    446486  targetClockBits += offset;
    447 #ifdef DEBUG_CALIBRATE 
     487#ifdef DEBUG_CALIBRATE
    448488  printk("offset = %u, emptyCall = %u, targetClockBits = %u\n",
    449489         offset, emptyCall, targetClockBits);
    450490  printk("slowLoopGranularity = %u fastLoopGranularity =  %u\n",
    451491         slowLoopGranularity, fastLoopGranularity);
    452 #endif 
     492#endif
    453493  slowLoop1ms = (targetClockBits - emptyCall) / slowLoopGranularity;
    454494  if (slowLoop1ms != 0) {
    455495    fastLoop1ms = targetClockBits % slowLoopGranularity;
    456496    if (fastLoop1ms > emptyCall) fastLoop1ms -= emptyCall;
    457   }   
     497  }
    458498  else
    459499    fastLoop1ms = targetClockBits - emptyCall / fastLoopGranularity;
     
    463503     * calibrate slow loop
    464504     */
    465  
     505
    466506    while(1)
    467507      {
     
    498538   * calibrate fast loop
    499539   */
    500  
     540
    501541  if (fastLoopGranularity != 0 ) {
    502542    while(1) {
     
    526566    }
    527567  }
    528 #ifdef DEBUG_CALIBRATE 
     568#ifdef DEBUG_CALIBRATE
    529569  printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
    530 #endif 
     570#endif
    531571  rtems_interrupt_enable(level);
    532  
     572
    533573}
    534574
     
    538578| Global Variables: loop1ms
    539579|        Arguments: timeToWait
    540 |          Returns: Nothing. 
     580|          Returns: Nothing.
    541581+--------------------------------------------------------------------------*/
    542582void
     
    551591
    552592}
    553 
    554 
    555 
    556 
    557 
    558 
Note: See TracChangeset for help on using the changeset viewer.