Changeset 23291e99 in rtems


Ignore:
Timestamp:
03/26/99 15:42:39 (25 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
39560f1
Parents:
aec5da4
Message:

Patch from Rosimildo DaSilva? <rdasilva@…> and
Emmanuel Raguet <raguet@…> to eliminate a problem
during the boot process on the pc386 BSP. On fast PC's the
calibration routine would hand.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/timer/timer.c

    raec5da4 r23291e99  
    2121| This code is base on:
    2222|   timer.c,v 1.7 1995/12/19 20:07:43 joel Exp - go32 BSP
     23|
     24| Rosimildo daSilva -ConnectTel, Inc - Fixed infinite loop in the Calibration
     25| routine. I've seen this problems with faster machines ( pentiums ). Sometimes
     26| RTEMS just hangs at startup.
     27|
    2328| With the following copyright notice:
    2429| **************************************************************************
     
    302307} /* Set_find_average_overhead */
    303308
    304 /*-------------------------------------------------------------------------+
    305 |         Function: Calibrate_loop_1ms
    306 |      Description: Set loop variable to calibrate a 1ms loop
    307 | Global Variables: loop1ms
    308 |        Arguments: none
    309 |          Returns: Nothing.
    310 +--------------------------------------------------------------------------*/
    311 void
    312 Calibrate_loop_1ms(void){
    313   unsigned int i;
    314   unsigned short loadedValue, offset;
    315   unsigned int timerValue;
    316   rtems_interrupt_level  level;
    317   unsigned short lsb, msb;
    318   unsigned char status;
    319  
    320  
    321   loop1ms = 100 ;
    322   timerValue = 2000;
    323   loadedValue = US_TO_TICK(2000);
    324  
    325   rtems_interrupt_disable(level);
    326 
    327   /*
    328    * Compute the offset to apply due to read counter register
    329    */
     309
     310
     311/*-------------------------------------------------------------------------+
     312| Description: Loads timer 0 with value passed as arguemnt.
     313| Returns: Nothing.
     314+--------------------------------------------------------------------------*/
     315inline void loadTimerValue( unsigned short loadedValue )
     316{
    330317  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    331318  outport_byte(TIMER_CNTR0, loadedValue >> 0 & 0xff);
    332319  outport_byte(TIMER_CNTR0, loadedValue >> 8 & 0xff);
    333 
     320}
     321
     322
     323/*-------------------------------------------------------------------------+
     324| Description: Waits until the counter on timer 0 reaches 0.
     325| Returns: Nothing.
     326+--------------------------------------------------------------------------*/
     327inline void waitTimerStatus( void )
     328{
     329  unsigned char status;
    334330  outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS); /* read Status counter 0 */
    335331  inport_byte(TIMER_CNTR0, status);
     
    338334    inport_byte(TIMER_CNTR0, status);
    339335  }
    340  
     336}
     337
     338
     339/*-------------------------------------------------------------------------+
     340| Description: Reads the current value of the timer, and converts the
     341|                          number of ticks to micro-seconds.   
     342| Returns: current number of microseconds since last value loaded..
     343+--------------------------------------------------------------------------*/
     344inline unsigned short readCurrentTimer()
     345{
     346  unsigned short lsb, msb;
    341347  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
    342348  inport_byte(TIMER_CNTR0, lsb);
    343349  inport_byte(TIMER_CNTR0, msb);
    344   offset = loadedValue - (unsigned short)((msb << 8) | lsb);
    345 
    346   while (timerValue > 1000){
     350  return TICK_TO_US( ( msb << 8 ) | lsb );
     351}
     352
     353
     354/*-------------------------------------------------------------------------+
     355 * clockbits - Read low order bits of timer 0 (the TOD clock)
     356 * This works only for the 8254 chips used in ATs and 386s.
     357 *
     358 * The timer runs in mode 3 (square wave mode), counting down
     359 * by twos, twice for each cycle. So it is necessary to read back the
     360 * OUTPUT pin to see which half of the cycle we're in. I.e., the OUTPUT
     361 * pin forms the most significant bit of the count. Unfortunately,
     362 * the 8253 in the PC/XT lacks a command to read the OUTPUT pin...
     363 *
     364 * The PC's clock design is soooo brain damaged...
     365 *
     366 * Rosimildo - I've got this routine from the KA9Q32 distribution and
     367 *                         have updated it for the RTEMS environment.
     368 +--------------------------------------------------------------------------*/
     369unsigned int clockbits(void)
     370{
     371        int i_state;
     372        unsigned int stat,count1, count;
     373
     374        do
     375        {
     376          outport_byte( 0x43, 0xc2 );    /* latch timer 0 count and status for reading */
     377          inport_byte( 0x40, stat );     /* get status of timer 0 */
     378          inport_byte( 0x40, count1 ); /* lsb of count */
     379          inport_byte( 0x40, count ); /* msb of count */
     380          count = count1 | ( count << 8 );
     381        } while(stat & 0x40);            /* reread if NULL COUNT bit set */
     382        stat = (stat & 0x80) << 8;       /* Shift OUTPUT to msb of 16-bit word */
     383        if(count == 0)
     384                return stat ^ 0x8000;   /* return complement of OUTPUT bit */
     385        else
     386                return count | stat;    /* Combine OUTPUT with counter */
     387}
     388
     389
     390/*-------------------------------------------------------------------------+
     391|         Function: Calibrate_loop_1ms
     392|      Description: Set loop variable to calibrate a 1ms loop
     393| Global Variables: loop1ms
     394|        Arguments: none
     395|          Returns: Nothing.
     396+--------------------------------------------------------------------------*/
     397void
     398Calibrate_loop_1ms(void)
     399{
     400  unsigned int i;
     401  unsigned short loadedValue, offset;
     402  unsigned int timerValue, t1_ref, t2_ref;
     403  rtems_interrupt_level  level;
     404  unsigned short lsb, msb;
     405  unsigned char status;
     406 
     407
     408  printk( "Calibrate_loop_1ms is starting,  please wait ( but not too loooong. )\n" );
     409 
     410  loop1ms = 200;
     411  timerValue = 0;
     412
     413  /* Let's load the timer with 2ms, initially */
     414  loadedValue = US_TO_TICK( 2000 );
     415 
     416  rtems_interrupt_disable(level);
     417  /*
     418   * Compute the offset to apply due to read counter register
     419   */
     420  offset = 0;
     421  loadTimerValue( loadedValue + offset );
     422  waitTimerStatus();
     423  t1_ref = clockbits();
     424  offset = loadedValue - readCurrentTimer();
     425  while( timerValue < 1000 )
     426  {
    347427    loop1ms++;
    348 
    349     /* load timer for 2ms+offset period */
    350     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    351     outport_byte(TIMER_CNTR0, (loadedValue+offset) >> 0 & 0xff);
    352     outport_byte(TIMER_CNTR0, (loadedValue+offset) >> 8 & 0xff);
    353 
    354     outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS); /* read Status counter 0 */
    355     inport_byte(TIMER_CNTR0, status);
    356     while (status & MSK_NULL_COUNT) {   /* wait for counter ready */
    357       outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS);
    358       inport_byte(TIMER_CNTR0, status);
    359     }
    360    
    361     for (i=0; i<loop1ms; i++)
    362       outport_byte(SLOW_DOWN_IO, 0);    /* write is # 1us */
    363 
    364     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
    365     inport_byte(TIMER_CNTR0, lsb);
    366     inport_byte(TIMER_CNTR0, msb);
    367     timerValue = TICK_TO_US((msb << 8) | lsb);
     428    loadTimerValue( loadedValue + offset );
     429    waitTimerStatus();
     430    t1_ref = clockbits();
     431    for( i=0; i < loop1ms; i++ )
     432       outport_byte( SLOW_DOWN_IO, 0 ); /* write is # 1us */
     433    t2_ref = clockbits();
     434    timerValue = TICK_TO_US( t1_ref - t2_ref );  /* timer0 is decrementing number of ticks  */
    368435  }
    369 
     436  printk( "Calibrate_loop_1ms timerValue=%d, loop1ms=%d, t1_ref=%x, clockbits=%x, delta=%d\n",
     437                   timerValue, loop1ms, t1_ref, t2_ref, t1_ref - t2_ref );
    370438  rtems_interrupt_enable(level);
    371439}
     440
     441
    372442
    373443/*-------------------------------------------------------------------------+
Note: See TracChangeset for help on using the changeset viewer.