Using the 8254 TimerCounter Understanding the role of
- Slides: 22
Using the 8254 Timer-Counter Understanding the role of the system’s 8254 programmable Interval-Timer/Counter
Displaying ‘Time-Of-Day’ • Algorithm steps: – Get the count of timer-interrupts so far today – Convert these ‘timer-ticks’ into seconds – Breakdown the total number of seconds today into Hours, Minutes, Seconds, and AM/PM – Convert numerical values into digit-strings – Output these results to the video terminal
Where’s the ‘tick’ counter? main memory 0 x 00500 0040: 006 C 0 x 00400 tick_count ROM-BIOS DATA AREA Interrupt Vector Table (for real-mode) 0 x 00000 Number of timer-tick interrupts so far today (longword at 0 x 0046 C)
Getting the ‘tick’ count • The ROM-BIOS interrupt-handler for the timer interrupt stores the tick-count as a 32 -bit integer located at address 0 x 046 C (it’s in the ROM-BIOS DATA AREA) • In real-mode, we can get it like this: xor mov mov %ax, %fs: 0 x 046 C, %eax, total_ticks # address segment zero # using FS register # copy tick-count to EAX # save in a local variable segment-override prefix (segment used would be %ds)
Converting ‘ticks’ to seconds total_seconds_today = total_ticks_today number of ticks-per-second The number of ‘ticks-per-second’ is based upon the way the PC’s timing hardware has been programmed
The 8254 PIT • The 8254 Programmable Interval-timer is used by the PC system for (1) generating timer-tick interrupts (rate is 18. 2 per sec), (2) performing dynamic memory-refresh (reads ram once every 15 microseconds), and (3) generates ‘beeps’ of PC speaker • When the speaker-function isn’t needed, the 8254 is available for other purposes
Input/Output frequencies • The input-pulses to each Timer-channel is a long established PC standard, based on the design of the chrystal oscillator chip: 1, 193, 182 pulses-per-second (Hertz) • The frequency of the output-pulses from any Timer-channel is determined by how that channel’s Latch was programmed
Three timer/counter ‘channels’ 8284 PCLK 1193182 Hz CLK 0 GATE 0 Channel 1 Port 0 x 61, bit #0 +5 V OUT 1 DRAM refresh Port 0 x 61, bit #5 CLK 2 GATE 2 Interrupt IRQ 0 Port 0 x 61, bit #4 CLK 1 GATE 1 OUT 0 Channel 2 8254 PIT Port 0 x 61, bit #1 OUT 2 AND speaker
Counter decrements when pulsed COUNT REGISTER CLK MSB LSB LATCH REGISTER GATE STATUS TIMER/COUNTER CHANNEL OUT
8254 Command-Port 7 6 CHANNEL Channel-ID 00 = chn 0 01 = chn 1 10 = chn 2 5 4 COMMAND 3 2 OUTPUT MODE 1 0 binary / BCD Output Mode Counting Mode Command-ID 000 = one-shot level 0 = binary 00 = Latch 001 = retriggerable 1 = BCD 01 = LSB r/w 010 = rate-generator 10 = MSB r/w 11 = LSB-MSB r/w 011 = square-wave 100 = software strobe 101 = hardware strobe Commands are sent to the 8254 via io/port 0 x 43
Programming a PIT channel • Step 1: send command to PIT (port 0 x 43) • Step 2: read or write the channel’s Latch – via port 0 x 40 for channel 0 – via port 0 x 41 for channel 1 – via port 0 x 42 for channel 2
Standard BIOS programming • For Channel 0 (the ‘timer-tick’ interrupt) the Latch is programmed during system startup with a value of zero • But the Timer interprets zero as 65, 536 • So the frequency of the output-pulses from Timer-channel 0 is equal to this quotient: output-frequency = input-frequency / frequency-divisor = 1193182 / 65536 (approximately 18. 2)
Consequently… • To compute ‘total_seconds’ from ‘total_ticks’: total_seconds = total_ticks / ticks_per_second = total_ticks / (1193182 / 65536) = ( total_ticks * 65536 ) / 1193183 • We can use the Pentium’s integer-arithmetic instructions MUL (multiply) and DIV (divide)
How ‘MUL’ works Before executing the MUL instruction… EAX reg (or mem) multiplicand (32 -bits) multiplier (32 -bits) 32 -bit operands Here’s the instruction… mull reg_or_mem After executing the MUL instruction… EDX EAX 64 -bit product (64 -bits)
How ‘DIV’ works Before executing the DIV instruction… EDX EAX dividend (64 -bits) 64 -bit dividend reg (or mem) divisor (32 -bits) 32 -bit operand Here’s the instruction… divl reg_or_mem After executing the DIV instruction… EDX EAX 32 -bit remainder 32 -bit quotient two results (32 -bits)
Implementing the conversion • So use MUL and DIV to convert ‘ticks’ into ‘seconds’, like this: # total_seconds = ( total_ticks * FREQ_DIVISOR ) / PULSES_PER_SEC mov mul mov div mov total_ticks, %eax $FREQ_DIVISOR, %ecx $PULSES_PER_SEC, %ecx %eax, total_seconds # Now integer-quotient is in EAX, and integer-remainder is in EDX
‘Time-Of-Day’ Format HH: MM: SS am/pm hours seconds minutes morning or afternoon So we need to compute four numerical values from the ‘total_seconds’ integer
Our four time-parameters We use these arithmetical ideas: – total_minutes = ( total_seconds / 60 ); ss = ( total_seconds % 60 ); – total_hours = (total_minutes / 60 ); mm = ( total_minutes % 60 ); – total_halfdays = (total_hours / 12 ); hh = (total_hours % 12 ); – Total_days = ( total_halfdays / 2 ); xm = total_halfdays % 2;
A subtle refinement • Our ‘total_seconds’ value was gotten with an integer-division operation, so there’s likely to be some ‘round-off’ error • How can we be sure we use the ‘closest’ integer to the actual quotient? • We should remember the ‘rounding’ rule! • When ‘remainder’ is equal or greater than 1/2 of ‘divisor’, ‘quotient’ gets incremented
How to implement rounding? • There is more than one way to do it – i. e. , the “amateur’s” way or the “expert’s” way • Knowledge of the Pentium’s architecture and instruction-set can assist • The ‘obvious’ method: • if ( 2 * remainder >= divisor ) ++quotient; • But this uses a multiply and a conditional jump-instruction (inefficient!)
Avoiding inefficiency… • Replace the ‘multiply’ with an ‘addition’ • Use ‘subtract’ and ‘add-with-carry’ instead of using ‘compare’ and ‘conditionally-jump’ # Recall: quotient was in EAX, remainder was in EDX, divisor was in ECX add %edx, %edx # doubles the remainder sub %ecx, %edx # computes: 2*quotient – divisor # now carry-flag is clear in case 2*quotient >= divisor cmc # complement the carry-flag bit # now carry-flag is set in case 2*quotient >= divisor adc $0, %eax # add the carry-flag to the quotient # So this achieves the same effect as the ‘rounding rule’, but wit no jump!
In-class exercise • Can you enhance our ‘timeoday. s’ demo to make it more dramatic (and later useful) by creating a loop within its ‘main’ routine, so it continues to read and display the time (until the user presses a key) • HINTS: Use an INT-0 x 16 keyboard service to ‘peek’ into the keyboard-queue, and omit the ‘n’ (newline) control-code from the ‘report’ message-string
- Timercounter
- Nicer land
- Timercounter
- 8254 block diagram
- Ic 8254
- 8254 block diagram
- Control word format of 8254
- Classify the modes of operation in 8253
- 8254 timer clock gating
- Understanding the role of culture
- Azure worker role
- Role taking krappmann
- Statuses and their related roles determine
- System collections generic
- Accumulator ac
- Hát kết hợp bộ gõ cơ thể
- Bổ thể
- Tỉ lệ cơ thể trẻ em
- Chó sói
- Tư thế worm breton là gì
- Chúa yêu trần thế
- Các môn thể thao bắt đầu bằng tiếng chạy