Changeset 23291e99 in rtems
- Timestamp:
- 03/26/99 15:42:39 (25 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 39560f1
- Parents:
- aec5da4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/i386/pc386/timer/timer.c
raec5da4 r23291e99 21 21 | This code is base on: 22 22 | 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 | 23 28 | With the following copyright notice: 24 29 | ************************************************************************** … … 302 307 } /* Set_find_average_overhead */ 303 308 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 +--------------------------------------------------------------------------*/ 315 inline void loadTimerValue( unsigned short loadedValue ) 316 { 330 317 outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); 331 318 outport_byte(TIMER_CNTR0, loadedValue >> 0 & 0xff); 332 319 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 +--------------------------------------------------------------------------*/ 327 inline void waitTimerStatus( void ) 328 { 329 unsigned char status; 334 330 outport_byte(TIMER_MODE, CMD_READ_BACK_STATUS); /* read Status counter 0 */ 335 331 inport_byte(TIMER_CNTR0, status); … … 338 334 inport_byte(TIMER_CNTR0, status); 339 335 } 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 +--------------------------------------------------------------------------*/ 344 inline unsigned short readCurrentTimer() 345 { 346 unsigned short lsb, msb; 341 347 outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH); 342 348 inport_byte(TIMER_CNTR0, lsb); 343 349 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 +--------------------------------------------------------------------------*/ 369 unsigned 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 +--------------------------------------------------------------------------*/ 397 void 398 Calibrate_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 { 347 427 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 */ 368 435 } 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 ); 370 438 rtems_interrupt_enable(level); 371 439 } 440 441 372 442 373 443 /*-------------------------------------------------------------------------+
Note: See TracChangeset
for help on using the changeset viewer.