|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『楼 主』:
一直存在的疑问:PC上8253计时器的精确频率到底是多少?
使用 LLM 解释/回答一下
PC机上8253计时器芯片的精确的输入频率到底是多少?
很多书上说PC机的8253的计时器#0的输出频率是每秒18.2次(每隔55ms触发一次),但都说这个只是约值,精确值有很长一串小数。计算机应该是靠整数运算的,那些小数值应该只是换算成现实时间的结果。所以我想知道精确的频率,于是查找了大量的资料,结果发现都有一点出入:
1.许多书上所说的(计数器#0)精确值:
F: 每秒18.2064819336次
T: 每隔54.925ms。
2.Terrv Dettmann《DOS Programmer's Reference》:
H: 由系统时钟每秒大约调用18.2次(每小时65536次)。
D: int 1Ah的00h功能: 该中断获取系统时钟计数器,该计数器从零点开始,每秒计数18.2065次。从零点(midnight)开始的一整天共需计86400秒,这段时间内的计数次数(时钟计数1573040次,经过的时间为86399.9129秒)。
3.Mazid《汇编语言、设计与接口技术》:8284芯片连接到一个14.31818MHz的晶振源,输出的Clr引脚是(8088中)CPU、内存(系统总线)的主频,1/3分频,4.772776MHz。PClk接8253/54计时器,1/6分频,2.386383MHz。在8284与8253之间存在一个72LS175的D触发器,所以频率又除以了2,1.1931817MHz。
4.在某些接口技术的书上说晶振源的频率周期是70ns,与内存速度匹配。
5.在很多计算机上,QueryPerformanceFrequency(Win32 API)的返回值是3579545。3579545 * 4 = 14318180,与3一致。
常数分析
~~~~~~~~
现在对这些常数进行计算分析:
第1种,根据频率(每秒18.2064819336次)
晶振源频率:18.2064819336Hz * 65536 * 12 = 14,318,160.0000049152Hz
周期:1s / 14,318,160.0000049152Hz = 0.000000069841376266200176256402804053989s = 69.841376266200176256402804053989ns
8253输入频率:18.2064819336Hz * 65536 = 1,193,180.0000004096Hz
周期:1s / 1,193,180.0000004096Hz = 0.00000083809651519440211507683364864787s = 838.09651519440211507683364864787ns
计时器#0输出频率:18.2064819336Hz
周期:1s / 18.2064819336Hz = 0.054925493219780337013675369997787s = 54.925493219780337013675369997787ms
计时器#0触发65536次:(1s / 18.2064819336Hz) * 65536 = 65536s / 18.2064819336Hz = 3599.597123651524166528229048175s
计时器#0触发1573040次:(1s / 18.2064819336Hz) * 1573040 = 1573040s / 18.2064819336Hz = 86399.997854443261335991904021318s
第1种,根据周期(每隔54.925ms)
晶振源频率:(1s / 54.925ms) * 65536 * 12 = (65536 * 12)s / 0.054925s = 14,318,288.575329995448338643604916Hz
周期:54.925ms / (65536 * 12) = 0.000000069840749104817708333333333333333s = 69.840749104817708333333333333333ns
8253输入频率:(1s / 54.925ms) * 65536 = 65536s / 0.054925s = 1,193,190.7146108329540282203004096Hz
周期:54.925ms / 65536 = 0.0000008380889892578125s = 838.0889892578125ns
计时器#0输出频率:1s / 54.925ms = 18.206645425580336822940373236231Hz
周期:54.925ms
计时器#0触发65536次:54.925ms * 65536 = 3599.5648s
计时器#0触发1573040次:54.925ms * 1573040 = 86399.222s
第2种,根据小时(每小时65536次)
晶振源频率:1s / (3600s / 65536 / 65536 / 12) = (65536 * 65536 * 12)s / 3600s = 14,316,557.653333333333333333333333Hz
周期:3600s / 65536 / 65536 / 12 = 3600s / (65536 * 65536 * 12) = 0.000000069849193096160888671875s = 69.849193096160888671875ns
8253输入频率:1s / (3600s / 65536 / 65536) = (65536*65536)s / 3600s = 1,193,046.4711111111111111111111111Hz
周期:3600s / 65536 / 65536 = 3600s / (65536 * 65536) = 0.0000008381903171539306640625s = 838.1903171539306640625ns
计时器#0输出频率:1s / (3600s / 65536) = 65536s / 3600s = 18.204444444444444444444444444444Hz
周期:3600s / 65536 = 0.054931640625s = 54.931640625ms
计时器#0触发65536次:3600s
计时器#0触发1573040次:(3600s / 65536) * 1573040 = (3600s * 1573040) / 65536 = 86409.66796875s
第2种,根据天(时钟计数1573040次,经过的时间为86399.9129秒)
晶振源频率:1s / (86399.9129s / 1573040 / 65536 / 12) = (1573040 * 65536 * 12)s / 86399.9129s = 14,318,174.078622248240715529702808Hz
周期:86399.9129s / 1573040 / 65536 / 12 = 86399.9129s / (1573040 * 65536 * 12) = 0.000000069841307593336928084579328349353s = 69.841307593336928084579328349353ns
8253输入频率:1s / (86399.9129s / 1573040 / 65536) = (1573040 * 65536)s / 86399.9129s = 1,193,181.1732185206867262941419007Hz
周期:86399.9129s / 1573040 / 65536 = 86399.9129s / (1573040 * 65536) = 0.00000083809569112004313701495194019224s = 838.09569112004313701495194019224ns
计时器#0输出频率:1s / (86399.9129s / 1573040) = 1573040s / 86399.9129s = 18.206499835487681377049165983592Hz
周期:86399.9129s / 1573040 = 0.054925439213243147027411890352439s = 54.925439213243147027411890352439ms
计时器#0触发65536次:(86399.9129s / 1573040) * 65536Hz = (86399.9129s * 65536) / 1573040 = 3599.5935842791028835884656461374s
计时器#0触发1573040次:86399.9129s
第3种(8284芯片连接到一个14.31818MHz的晶振源)
晶振源频率:14.31818MHz = 14,318,180Hz
周期:1s / 14,318,180Hz = 0.000000069841278710003645714748662190306s = 69.841278710003645714748662190306ns
8253输入频率:14,318,180Hz / 12 = 1,193,181.6666666666666666666666667Hz
周期:1s / (14,318,180Hz / 12) = 12s / 14,318,180Hz = 0.00000083809534452004374857698394628368s = 838.09534452004374857698394628368ns
计时器#0输出频率:14,318,180Hz / 12 / 65536 = 14,318,180Hz / (12 * 65536) = 18.206507364908854166666666666667Hz
周期:1s / (14,318,180Hz / 12 / 65536) = (12 * 65536)s / 14,318,180Hz = 0.054925416498465587106741219903647s = 54.925416498465587106741219903647ms
计时器#0触发65536次:(1s / (14,318,180Hz / 12 / 65536)) * 65536 = (12 * 65536 * 65536)s / 14,318,180Hz = 3599.5920956434407166273925876054s
计时器#0触发1573040次:(1s / (14,318,180Hz / 12 / 65536)) * 1573040 = (12 * 65536 * 1573040)s / 14,318,180Hz = 86399.877168746307142388208557233s
第4种(晶振源的频率周期是70ns,与内存速度匹配)
晶振源频率:1s / 0.00000007s = 14,285,714.285714285714285714285714Hz
周期:70ns = 0.00000007s
8253输入频率:1s / (0.00000007s * 12) = 1,190,476.1904761904761904761904762Hz
周期:0.00000007s * 12 = 0.00000084s = 840ns
计时器#0输出频率:1s / (0.00000007s * 12 * 65536) = 18.165225074404761904761904761905Hz
周期:0.00000007s * 12 * 65536 = 0.05505024s = 55.05024ms
计时器#0触发65536次:(0.00000007s * 12 * 65536) * 65536 = 3607.77252864s
计时器#0触发1573040次:(0.00000007s * 12 * 65536) * 1573040 = 86596.2295296s
总表
~~~~
晶振源频率(Hz):
1F: 14,318,160.0000049152
1T: 14,318,288.575329995448338643604916
2H: 14,316,557.653333333333333333333333
2D: 14,318,174.078622248240715529702808
3 : 14,318,180
4 : 14,285,714.285714285714285714285714
晶振源周期(ns):
1F: 69.841376266200176256402804053989
1T: 69.840749104817708333333333333333
2H: 69.849193096160888671875
2D: 69.841307593336928084579328349353
3 : 69.841278710003645714748662190306
4 : 70
8253输入频率(Hz):
1F: 1,193,180.0000004096
1T: 1,193,190.7146108329540282203004096
2H: 1,193,046.4711111111111111111111111
2D: 1,193,181.1732185206867262941419007
3 : 1,193,181.6666666666666666666666667
4 : 1,190,476.1904761904761904761904762
8253输入周期(ns):
1F: 838.09651519440211507683364864787
1T: 838.0889892578125
2H: 838.1903171539306640625
2D: 838.09569112004313701495194019224
3 : 838.09534452004374857698394628368
4 : 840
计时器#0输出频率(Hz):
1F: 18.2064819336
1T: 18.206645425580336822940373236231
2H: 18.204444444444444444444444444444
2D: 18.206499835487681377049165983592
3 : 18.206507364908854166666666666667
4 : 18.165225074404761904761904761905
计时器#0输出周期(ms):
1F: 54.925493219780337013675369997787
1T: 54.925
2H: 54.931640625
2D: 54.925439213243147027411890352439
3 : 54.925416498465587106741219903647
4 : 55.05024
计时器#0触发65536次(s):
1F: 3599.597123651524166528229048175
1T: 3599.5648
2H: 3600
2D: 3599.5935842791028835884656461374
3 : 3599.5920956434407166273925876054
4 : 3607.77252864
计时器#0触发1573040次(s):
1F: 86399.997854443261335991904021318
1T: 86399.222
2H: 86409.66796875
2D: 86399.9129
3 : 86399.877168746307142388208557233
4 : 86596.2295296
结论
~~~~
个人认为最可信的是《汇编语言、设计与接口技术》上的说法,晶振源频率为14,318,180Hz,因为它跟许多数字吻合。
PS: 我一直存在这个疑问,但是一直没有去研究。直到前两天看到风云的一篇文章《不太精准的时钟》( http://blog.codingnow.com/2006/05/iaeeoeo.html)后,才认识到这个问题的严重性,引起我关注这个问题。
Last edited by zyl910 on 2006-6-3 at 12:44 ]
What is the exact input frequency of the 8253 timer chip on a PC?
Many books say that the output frequency of timer #0 of the 8253 on a PC is 18.2 times per second (triggering once every 55ms), but all say this is only an approximate value, and the exact value has a long string of decimals. Computers should rely on integer operations, and those decimal values should just be the result of converting to real time. So I wanted to know the exact frequency, so I looked up a lot of materials, and it turned out that there were some differences:
1. The exact value (counter #0) as said in many books:
F: 18.2064819336 times per second
T: once every 54.925ms.
2. Terrv Dettmann's "DOS Programmer's Reference":
H: The system clock is called about 18.2 times per second (65536 times per hour).
D: The 00h function of int 1Ah: This interrupt obtains the system clock counter, which starts from zero and counts 18.2065 times per second. The total number of counts in a full day (from midnight) is 1573040 counts, and the elapsed time is 86399.9129 seconds.
3. Mazid's "Assembly Language, Design and Interface Technology": The 8284 chip is connected to a 14.31818MHz crystal oscillator source. The Clr pin output is the main frequency of the CPU, memory (system bus) in 8088, divided by 3, 4.772776MHz. PClk is connected to the 8253/54 timer, divided by 6, 2.386383MHz. There is a 72LS175 D flip-flop between the 8284 and the 8253, so the frequency is divided by 2 again, 1.1931817MHz.
4. Some interface technology books say that the frequency period of the crystal oscillator source is 70ns, matching the memory speed.
5. On many computers, the return value of QueryPerformanceFrequency (Win32 API) is 3579545. 3579545 * 4 = 14318180, which matches 3.
Constant Analysis
~~~~~~~~
Now analyze these constants:
The first type, according to the frequency (18.2064819336 times per second)
Crystal oscillator source frequency: 18.2064819336Hz * 65536 * 12 = 14,318,160.0000049152Hz
Period: 1s / 14,318,160.0000049152Hz = 0.000000069841376266200176256402804053989s = 69.841376266200176256402804053989ns
8253 input frequency: 18.2064819336Hz * 65536 = 1,193,180.0000004096Hz
Period: 1s / 1,193,180.0000004096Hz = 0.00000083809651519440211507683364864787s = 838.09651519440211507683364864787ns
Timer #0 output frequency: 18.2064819336Hz
Period: 1s / 18.2064819336Hz = 0.054925493219780337013675369997787s = 54.925493219780337013675369997787ms
Timer #0 triggers 65536 times: (1s / 18.2064819336Hz) * 65536 = 65536s / 18.2064819336Hz = 3599.597123651524166528229048175s
Timer #0 triggers 1573040 times: (1s / 18.2064819336Hz) * 1573040 = 1573040s / 18.2064819336Hz = 86399.997854443261335991904021318s
The first type, according to the period (once every 54.925ms)
Crystal oscillator source frequency: (1s / 54.925ms) * 65536 * 12 = (65536 * 12)s / 0.054925s = 14,318,288.575329995448338643604916Hz
Period: 54.925ms / (65536 * 12) = 0.000000069840749104817708333333333333333s = 69.840749104817708333333333333333ns
8253 input frequency: (1s / 54.925ms) * 65536 = 65536s / 0.054925s = 1,193,190.7146108329540282203004096Hz
Period: 54.925ms / 65536 = 0.0000008380889892578125s = 838.0889892578125ns
Timer #0 output frequency: 1s / 54.925ms = 18.206645425580336822940373236231Hz
Period: 54.925ms
Timer #0 triggers 65536 times: 54.925ms * 65536 = 3599.5648s
Timer #0 triggers 1573040 times: 54.925ms * 1573040 = 86399.222s
The second type, according to the hour (65536 times per hour)
Crystal oscillator source frequency: 1s / (3600s / 65536 / 65536 / 12) = (65536 * 65536 * 12)s / 3600s = 14,316,557.653333333333333333333333Hz
Period: 3600s / 65536 / 65536 / 12 = 3600s / (65536 * 65536 * 12) = 0.000000069849193096160888671875s = 69.849193096160888671875ns
8253 input frequency: 1s / (3600s / 65536 / 65536) = (65536*65536)s / 3600s = 1,193,046.4711111111111111111111111Hz
Period: 3600s / 65536 / 65536 = 3600s / (65536 * 65536) = 0.0000008381903171539306640625s = 838.1903171539306640625ns
Timer #0 output frequency: 1s / (3600s / 65536) = 65536s / 3600s = 18.204444444444444444444444444444Hz
Period: 3600s / 65536 = 0.054931640625s = 54.931640625ms
Timer #0 triggers 65536 times: 3600s
Timer #0 triggers 1573040 times: (3600s / 65536) * 1573040 = (3600s * 1573040) / 65536 = 86409.66796875s
The second type, according to the day (clock counts 1573040 times, elapsed time is 86399.9129 seconds)
Crystal oscillator source frequency: 1s / (86399.9129s / 1573040 / 65536 / 12) = (1573040 * 65536 * 12)s / 86399.9129s = 14,318,174.078622248240715529702808Hz
Period: 86399.9129s / 1573040 / 65536 / 12 = 86399.9129s / (1573040 * 65536 * 12) = 0.000000069841307593336928084579328349353s = 69.841307593336928084579328349353ns
8253 input frequency: 1s / (86399.9129s / 1573040 / 65536) = (1573040 * 65536)s / 86399.9129s = 1,193,181.1732185206867262941419007Hz
Period: 86399.9129s / 1573040 / 65536 = 86399.9129s / (1573040 * 65536) = 0.00000083809569112004313701495194019224s = 838.09569112004313701495194019224ns
Timer #0 output frequency: 1s / (86399.9129s / 1573040) = 1573040s / 86399.9129s = 18.206499835487681377049165983592Hz
Period: 86399.9129s / 1573040 = 0.054925439213243147027411890352439s = 54.925439213243147027411890352439ms
Timer #0 triggers 65536 times: (86399.9129s / 1573040) * 65536Hz = (86399.9129s * 65536) / 1573040 = 3599.5935842791028835884656461374s
Timer #0 triggers 1573040 times: 86399.9129s
The third type (8284 chip connected to a 14.31818MHz crystal oscillator source)
Crystal oscillator source frequency: 14.31818MHz = 14,318,180Hz
Period: 1s / 14,318,180Hz = 0.000000069841278710003645714748662190306s = 69.841278710003645714748662190306ns
8253 input frequency: 14,318,180Hz / 12 = 1,193,181.6666666666666666666666667Hz
Period: 1s / (14,318,180Hz / 12) = 12s / 14,318,180Hz = 0.00000083809534452004374857698394628368s = 838.09534452004374857698394628368ns
Timer #0 output frequency: 14,318,180Hz / 12 / 65536 = 14,318,180Hz / (12 * 65536) = 18.206507364908854166666666666667Hz
Period: 1s / (14,318,180Hz / 12 / 65536) = (12 * 65536)s / 14,318,180Hz = 0.054925416498465587106741219903647s = 54.925416498465587106741219903647ms
Timer #0 triggers 65536 times: (1s / (14,318,180Hz / 12 / 65536)) * 65536 = (12 * 65536 * 65536)s / 14,318,180Hz = 3599.5920956434407166273925876054s
Timer #0 triggers 1573040 times: (1s / (14,318,180Hz / 12 / 65536)) * 1573040 = (12 * 65536 * 1573040)s / 14,318,180Hz = 86399.877168746307142388208557233s
The fourth type (the frequency period of the crystal oscillator source is 70ns, matching the memory speed)
Crystal oscillator source frequency: 1s / 0.00000007s = 14,285,714.285714285714285714285714Hz
Period: 70ns = 0.00000007s
8253 input frequency: 1s / (0.00000007s * 12) = 1,190,476.1904761904761904761904762Hz
Period: 0.00000007s * 12 = 0.00000084s = 840ns
Timer #0 output frequency: 1s / (0.00000007s * 12 * 65536) = 18.165225074404761904761904761905Hz
Period: 0.00000007s * 12 * 65536 = 0.05505024s = 55.05024ms
Timer #0 triggers 65536 times: (0.00000007s * 12 * 65536) * 65536 = 3607.77252864s
Timer #0 triggers 1573040 times: (0.00000007s * 12 * 65536) * 1573040 = 86596.2295296s
Total Table
~~~~
Crystal oscillator source frequency (Hz):
1F: 14,318,160.0000049152
1T: 14,318,288.575329995448338643604916
2H: 14,316,557.653333333333333333333333
2D: 14,318,174.078622248240715529702808
3 : 14,318,180
4 : 14,285,714.285714285714285714285714
Crystal oscillator source period (ns):
1F: 69.841376266200176256402804053989
1T: 69.840749104817708333333333333333
2H: 69.849193096160888671875
2D: 69.841307593336928084579328349353
3 : 69.841278710003645714748662190306
4 : 70
8253 input frequency (Hz):
1F: 1,193,180.0000004096
1T: 1,193,190.7146108329540282203004096
2H: 1,193,046.4711111111111111111111111
2D: 1,193,181.1732185206867262941419007
3 : 1,193,181.6666666666666666666666667
4 : 1,190,476.1904761904761904761904762
8253 input period (ns):
1F: 838.09651519440211507683364864787
1T: 838.0889892578125
2H: 838.1903171539306640625
2D: 838.09569112004313701495194019224
3 : 838.09534452004374857698394628368
4 : 840
Timer #0 output frequency (Hz):
1F: 18.2064819336
1T: 18.206645425580336822940373236231
2H: 18.204444444444444444444444444444
2D: 18.206499835487681377049165983592
3 : 18.206507364908854166666666666667
4 : 18.165225074404761904761904761905
Timer #0 output period (ms):
1F: 54.925493219780337013675369997787
1T: 54.925
2H: 54.931640625
2D: 54.925439213243147027411890352439
3 : 54.925416498465587106741219903647
4 : 55.05024
Timer #0 triggers 65536 times (s):
1F: 3599.597123651524166528229048175
1T: 3599.5648
2H: 3600
2D: 3599.5935842791028835884656461374
3 : 3599.5920956434407166273925876054
4 : 3607.77252864
Timer #0 triggers 1573040 times (s):
1F: 86399.997854443261335991904021318
1T: 86399.222
2H: 86409.66796875
2D: 86399.9129
3 : 86399.877168746307142388208557233
4 : 86596.2295296
Conclusion
~~~~
Personally, I think the statement in "Assembly Language, Design and Interface Technology" is the most credible, with a crystal oscillator source frequency of 14,318,180Hz, because it matches many numbers.
PS: I have always had this question, but I never studied it. Until a few days ago, I saw an article by Fengyun "Not Very Accurate Clock" ( http://blog.codingnow.com/2006/05/iaeeoeo.html) and then realized the seriousness of this problem, which caught my attention.
Last edited by zyl910 on 2006-6-3 at 12:44 ]
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-3 12:40 |
|
|
Scott0902
中级用户
  
积分 466
发帖 237
注册 2005-10-12
状态 离线
|
|
2006-6-3 14:03 |
|
|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第 3 楼』:
使用 LLM 解释/回答一下
刚才又翻了一下《图形程序开发人员指南(Michael Abrash's Graphics Programming Black Book Special Editior)》的“Zen timer”,发现该代码采用的(输入频率周期)是0.8381ms(ZTimerReport函数):
;
; *** Listing 3-1 ***
;
; The precision Zen timer (PZTIMER.ASM)
;
; Uses the 8253 timer to time the performance of code that takes
; less than about 54 milliseconds to execute, with a resolution
; of better than 10 microseconds.
;
; By Michael Abrash
;
; Externally callable routines:
;
; ZTimerOn: Starts the Zen timer, with interrupts disabled.
;
; ZTimerOff: Stops the Zen timer, saves the timer count,
; times the overhead code, and restores interrupts to the
; state they were in when ZTimerOn was called.
;
; ZTimerReport: Prints the net time that passed between starting
; and stopping the timer.
;
; Note: If longer than about 54 ms passes between ZTimerOn and
; ZTimerOff calls, the timer turns over and the count is
; inaccurate. When this happens, an error message is displayed
; instead of a count. The long-period Zen timer should be used
; in such cases.
;
; Note: Interrupts *MUST* be left off between calls to ZTimerOn
; and ZTimerOff for accurate timing and for detection of
; timer overflow.
;
; Note: These routines can introduce slight inaccuracies into the
; system clock count for each code section timed even if
; timer 0 doesn't overflow. If timer 0 does overflow, the
; system clock can become slow by virtually any amount of
; time, since the system clock can't advance while the
; precison timer is timing. Consequently, it's a good idea
; to reboot at the end of each timing session. (The
; battery-backed clock, if any, is not affected by the Zen
; timer.)
;
; All registers, and all flags except the interrupt flag, are
; preserved by all routines. Interrupts are enabled and then disabled
; by ZTimerOn, and are restored by ZTimerOff to the state they were
; in when ZTimerOn was called.
;
Code segment word public 'CODE'
assume cs:Code, ds:nothing
public ZTimerOn, ZTimerOff, ZTimerReport
;
; Base address of the 8253 timer chip.
;
BASE_8253 equ 40h
;
; The address of the timer 0 count registers in the 8253.
;
TIMER_0_8253 equ BASE_8253 + 0
;
; The address of the mode register in the 8253.
;
MODE_8253 equ BASE_8253 + 3
;
; The address of Operation Command Word 3 in the 8259 Programmable
; Interrupt Controller (PIC) (write only, and writable only when
; bit 4 of the byte written to this address is 0 and bit 3 is 1).
;
OCW3 equ 20h
;
; The address of the Interrupt Request register in the 8259 PIC
; (read only, and readable only when bit 1 of OCW3 = 1 and bit 0
; of OCW3 = 0).
;
IRR equ 20h
;
; Macro to emulate a POPF instruction in order to fix the bug in some
; 80286 chips which allows interrupts to occur during a POPF even when
; interrupts remain disabled.
;
MPOPF macro
local p1, p2
jmp short p2
p1: iret ;jump to pushed address & pop flags
p2: push cs ;construct far return address to
call p1 ; the next instruction
endm
;
; Macro to delay briefly to ensure that enough time has elapsed
; between successive I/O accesses so that the device being accessed
; can respond to both accesses even on a very fast PC.
;
DELAY macro
jmp $+2
jmp $+2
jmp $+2
endm
OriginalFlags db ? ;storage for upper byte of
; FLAGS register when
; ZTimerOn called
TimedCount dw ? ;timer 0 count when the timer
; is stopped
ReferenceCount dw ? ;number of counts required to
; execute timer overhead code
OverflowFlag db ? ;used to indicate whether the
; timer overflowed during the
; timing interval
;
; String printed to report results.
;
OutputStr label byte
db 0dh, 0ah, 'Timed count: ', 5 dup (?)
ASCIICountEnd label byte
db ' microseconds', 0dh, 0ah
db '$'
;
; String printed to report timer overflow.
;
OverflowStr label byte
db 0dh, 0ah
db '****************************************************'
db 0dh, 0ah
db '* The timer overflowed, so the interval timed was *'
db 0dh, 0ah
db '* too long for the precision timer to measure. *'
db 0dh, 0ah
db '* Please perform the timing test again with the *'
db 0dh, 0ah
db '* long-period timer. *'
db 0dh, 0ah
db '****************************************************'
db 0dh, 0ah
db '$'
;********************************************************************
;* Routine called to start timing. *
;********************************************************************
ZTimerOn proc near
;
; Save the context of the program being timed.
;
push ax
pushf
pop ax ;get flags so we can keep
; interrupts off when leaving
; this routine
mov cs:,ah ;remember the state of the
; Interrupt flag
and ah,0fdh ;set pushed interrupt flag
; to 0
push ax
;
; Turn on interrupts, so the timer interrupt can occur if it's
; pending.
;
sti
;
; Set timer 0 of the 8253 to mode 2 (divide-by-N), to cause
; linear counting rather than count-by-two counting. Also
; leaves the 8253 waiting for the initial timer 0 count to
; be loaded.
;
mov al,00110100b ;mode 2
out MODE_8253,al
;
; Set the timer count to 0, so we know we won't get another
; timer interrupt right away.
; Note: this introduces an inaccuracy of up to 54 ms in the system
; clock count each time it is executed.
;
DELAY
sub al,al
out TIMER_0_8253,al ;lsb
DELAY
out TIMER_0_8253,al ;msb
;
; Wait before clearing interrupts to allow the interrupt generated
; when switching from mode 3 to mode 2 to be recognized. The delay
; must be at least 210 ns long to allow time for that interrupt to
; occur. Here, 10 jumps are used for the delay to ensure that the
; delay time will be more than long enough even on a very fast PC.
;
rept 10
jmp $+2
endm
;
; Disable interrupts to get an accurate count.
;
cli
;
; Set the timer count to 0 again to start the timing interval.
;
mov al,00110100b ;set up to load initial
out MODE_8253,al ; timer count
DELAY
sub al,al
out TIMER_0_8253,al ;load count lsb
DELAY
out TIMER_0_8253,al ;load count msb
;
; Restore the context and return.
;
MPOPF ;keeps interrupts off
pop ax
ret
ZTimerOn endp
;********************************************************************
;* Routine called to stop timing and get count. *
;********************************************************************
ZTimerOff proc near
;
; Save the context of the program being timed.
;
push ax
push cx
pushf
;
; Latch the count.
;
mov al,00000000b ;latch timer 0
out MODE_8253,al
;
; See if the timer has overflowed by checking the 8259 for a pending
; timer interrupt.
;
mov al,00001010b ;OCW3, set up to read
out OCW3,al ; Interrupt Request register
DELAY
in al,IRR ;read Interrupt Request
; register
and al,1 ;set AL to 1 if IRQ0 (the
; timer interrupt) is pending
mov cs:,al ;store the timer overflow
; status
;
; Allow interrupts to happen again.
;
sti
;
; Read out the count we latched earlier.
;
in al,TIMER_0_8253 ;least significant byte
DELAY
mov ah,al
in al,TIMER_0_8253 ;most significant byte
xchg ah,al
neg ax ;convert from countdown
; remaining to elapsed
; count
mov cs:,ax
; Time a zero-length code fragment, to get a reference for how
; much overhead this routine has. Time it 16 times and average it,
; for accuracy, rounding the result.
;
mov cs:,0
mov cx,16
cli ;interrupts off to allow a
; precise reference count
RefLoop:
call ReferenceZTimerOn
call ReferenceZTimerOff
loop RefLoop
sti
add cs:,8 ;total + (0.5 * 16)
mov cl,4
shr cs:,cl ;(total) / 16 + 0.5
;
; Restore original interrupt state.
;
pop ax ;retrieve flags when called
mov ch,cs: ;get back the original upper
; byte of the FLAGS register
and ch,not 0fdh ;only care about original
; interrupt flag...
and ah,0fdh ;...keep all other flags in
; their current condition
or ah,ch ;make flags word with original
; interrupt flag
push ax ;prepare flags to be popped
;
; Restore the context of the program being timed and return to it.
;
MPOPF ;restore the flags with the
; original interrupt state
pop cx
pop ax
ret
ZTimerOff endp
;
; Called by ZTimerOff to start timer for overhead measurements.
;
ReferenceZTimerOn proc near
;
; Save the context of the program being timed.
;
push ax
pushf ;interrupts are already off
;
; Set timer 0 of the 8253 to mode 2 (divide-by-N), to cause
; linear counting rather than count-by-two counting.
;
mov al,00110100b ;set up to load
out MODE_8253,al ; initial timer count
DELAY
;
; Set the timer count to 0.
;
sub al,al
out TIMER_0_8253,al ;load count lsb
DELAY
out TIMER_0_8253,al ;load count msb
;
; Restore the context of the program being timed and return to it.
;
MPOPF
pop ax
ret
ReferenceZTimerOn endp
;
; Called by ZTimerOff to stop timer and add result to ReferenceCount
; for overhead measurements.
;
ReferenceZTimerOff proc near
;
; Save the context of the program being timed.
;
push ax
push cx
pushf
;
; Latch the count and read it.
;
mov al,00000000b ;latch timer 0
out MODE_8253,al
DELAY
in al,TIMER_0_8253 ;lsb
DELAY
mov ah,al
in al,TIMER_0_8253 ;msb
xchg ah,al
neg ax ;convert from countdown
; remaining to amount
; counted down
add cs:,ax
;
; Restore the context of the program being timed and return to it.
;
MPOPF
pop cx
pop ax
ret
ReferenceZTimerOff endp
;********************************************************************
;* Routine called to report timing results. *
;********************************************************************
ZTimerReport proc near
pushf
push ax
push bx
push cx
push dx
push si
push ds
;
push cs ;DOS functions require that DS point
pop ds ; to text to be displayed on the screen
assume ds:Code
;
; Check for timer 0 overflow.
;
cmp ,0
jz PrintGoodCount
mov dx,offset OverflowStr
mov ah,9
int 21h
jmp short EndZTimerReport
;
; Convert net count to decimal ASCII in microseconds.
;
PrintGoodCount:
mov ax,
sub ax,
mov si,offset ASCIICountEnd - 1
;
; Convert count to microseconds by multiplying by .8381.
;
mov dx,8381
mul dx
mov bx,10000
div bx ;* .8381 = * 8381 / 10000
;
; Convert time in microseconds to 5 decimal ASCII digits.
;
mov bx,10
mov cx,5
CTSLoop:
sub dx,dx
div bx
add dl,'0'
mov ,dl
dec si
loop CTSLoop
;
; Print the results.
;
mov ah,9
mov dx,offset OutputStr
int 21h
;
EndZTimerReport:
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
MPOPF
ret
ZTimerReport endp
Code ends
end
以下是《图形程序开发人员指南》对8253的说明,与《汇编语言、设计与接口技术》一致:
The 8253 actually contains three timers, as shown in Figure 3.1. All three timers are driven by the system board’s 14.31818 MHz crystal, divided by 12 to yield a 1.19318 MHz clock to the timers, so the timers count once every 838.1 ns. Each of the three timers counts down in a programmable way, generating a signal on its output pin when it counts down to 0. Each timer is capable of being halted at any time via a 0 level on its gate inputw; hen a timer’s gate input is 1, that timer counts constantly. All in all, the 8253’s timers are inherently very flexible timing devices; unfortunately, much of that flexibility depends on how the timers are connected to external circuitry, and in the PC the timers are connected with specific purposes in mind.
Just now I flipped through "Graphics Programmer's Guide (Michael Abrash's Graphics Programming Black Book Special Editior)" again, and found that the code uses an (input frequency period) of 0.8381ms (ZTimerReport function):
;
; *** Listing 3-1 ***
;
; Precision Zen timer (PZTIMER.ASM)
;
; Uses the 8253 timer to time code that takes less than about 54 milliseconds to execute, with a resolution better than 10 microseconds.
;
; By Michael Abrash
;
; Externally callable routines:
;
; ZTimerOn: Starts the Zen timer, with interrupts disabled.
;
; ZTimerOff: Stops the Zen timer, saves the timer count, times the overhead code, and restores interrupts to the state they were in when ZTimerOn was called.
;
; ZTimerReport: Prints the net time that passed between starting and stopping the timer.
;
; Note: If more than about 54 ms passes between ZTimerOn and ZTimerOff calls, the timer overflows and the count is inaccurate. In this case, an error message is displayed instead of a count. In such cases, the long - period Zen timer should be used.
;
; Note: For accurate timing and detection of timer overflow, interrupts must remain off between calls to ZTimerOn and ZTimerOff.
;
; Note: Even if timer 0 does not overflow, these routines may introduce slight inaccuracies into the system clock count for each timed code section. If timer 0 overflows, the system clock can slow down by almost any amount because the system clock cannot advance while the precision timer is timing. Therefore, it is a good idea to reboot at the end of each timing session. (The battery - backed clock, if any, is not affected by the Zen timer.)
;
All registers and all flags except the interrupt flag are preserved by all routines. ZTimerOn enables and then disables interrupts, and ZTimerOff restores interrupts to the state they were in when ZTimerOn was called.
Code segment word public 'CODE'
assume cs:Code, ds:nothing
public ZTimerOn, ZTimerOff, ZTimerReport
;
; Base address of 8253 timer chip.
;
BASE_8253 equ 40h
;
; Address of timer 0 count register in 8253.
;
TIMER_0_8253 equ BASE_8253 + 0
;
; Address of mode register in 8253.
;
MODE_8253 equ BASE_8253 + 3
;
; Address of Operation Command Word 3 in 8259 Programmable Interrupt Controller (PIC) (write - only, and writable only when bit 4 of the byte written to this address is 0 and bit 3 is 1).
;
OCW3 equ 20h
;
; Address of Interrupt Request register in 8259 PIC (read - only, and readable only when bit 1 of OCW3 = 1 and bit 0 of OCW3 = 0).
;
IRR equ 20h
;
; Macro to simulate POPF instruction to fix the bug in some 80286 chips that allows interrupts to occur during POPF even when interrupts are still disabled.
;
MPOPF macro
local p1, p2
jmp short p2
p1: iret ;jump to pushed address & pop flags
p2: push cs ;construct far return address to
call p1 ; the next instruction
endm
;
; Macro to briefly delay to ensure that enough time has elapsed between successive I/O accesses so that the accessed device can respond to both accesses even on a very fast PC.
;
DELAY macro
jmp $+2
jmp $+2
jmp $+2
endm
OriginalFlags db ? ;storage for upper byte of
; FLAGS register when
; ZTimerOn called
TimedCount dw ? ;timer 0 count when the timer
; is stopped
ReferenceCount dw ? ;number of counts required to
; execute timer overhead code
OverflowFlag db ? ;used to indicate whether the
; timer overflowed during the
; timing interval
;
; String printed to report results.
;
OutputStr label byte
db 0dh, 0ah, 'Timed count: ', 5 dup (?)
ASCIICountEnd label byte
db ' microseconds', 0dh, 0ah
db '$'
;
; String printed to report timer overflow.
;
OverflowStr label byte
db 0dh, 0ah
db '****************************************************'
db 0dh, 0ah
db '* The timer overflowed, so the interval timed was *'
db 0dh, 0ah
db '* too long for the precision timer to measure. *'
db 0dh, 0ah
db '* Please perform the timing test again with the *'
db 0dh, 0ah
db '* long - period timer. *'
db 0dh, 0ah
db '****************************************************'
db 0dh, 0ah
db '$'
;********************************************************************
;* Routine called to start timing. *
;********************************************************************
ZTimerOn proc near
;
; Save the context of the program being timed.
;
push ax
pushf
pop ax ;get flags so we can keep
; interrupts off when leaving
; this routine
mov cs:,ah ;remember the state of the
; Interrupt flag
and ah,0fdh ;set pushed interrupt flag
; to 0
push ax
;
; Turn on interrupts, so the timer interrupt can occur if it's
; pending.
;
sti
;
; Set timer 0 of 8253 to mode 2 (divide - by - N), to cause
; linear counting rather than count - by - two counting. Also
; leaves the 8253 waiting for the initial timer 0 count to
; be loaded.
;
mov al,00110100b ;mode 2
out MODE_8253,al
;
; Set the timer count to 0, so we know we won't get another
; timer interrupt right away.
; Note: this introduces an inaccuracy of up to 54 ms in the system
; clock count each time it is executed.
;
DELAY
sub al,al
out TIMER_0_8253,al ;lsb
DELAY
out TIMER_0_8253,al ;msb
;
; Wait before clearing interrupts to allow the interrupt generated
; when switching from mode 3 to mode 2 to be recognized. The delay
; must be at least 210 ns long to allow time for that interrupt to
; occur. Here, 10 jumps are used for the delay to ensure that the
; delay time will be more than long enough even on a very fast PC.
;
rept 10
jmp $+2
endm
;
; Disable interrupts to get an accurate count.
;
cli
;
; Set the timer count to 0 again to start the timing interval.
;
mov al,00110100b ;set up to load initial
out MODE_8253,al ; timer count
DELAY
sub al,al
out TIMER_0_8253,al ;load count lsb
DELAY
out TIMER_0_8253,al ;load count msb
;
; Restore the context and return.
;
MPOPF ;keeps interrupts off
pop ax
ret
ZTimerOn endp
;********************************************************************
;* Routine called to stop timing and get count. *
;********************************************************************
ZTimerOff proc near
;
; Save the context of the program being timed.
;
push ax
push cx
pushf
;
; Latch the count.
;
mov al,00000000b ;latch timer 0
out MODE_8253,al
;
; See if the timer has overflowed by checking the 8259 for a pending
; timer interrupt.
;
mov al,00001010b ;OCW3, set up to read
out OCW3,al ; Interrupt Request register
DELAY
in al,IRR ;read Interrupt Request
; register
and al,1 ;set AL to 1 if IRQ0 (the
; timer interrupt) is pending
mov cs:,al ;store the timer overflow
; status
;
; Allow interrupts to happen again.
;
sti
;
; Read out the count we latched earlier.
;
in al,TIMER_0_8253 ;least significant byte
DELAY
mov ah,al
in al,TIMER_0_8253 ;most significant byte
xchg ah,al
neg ax ;convert from countdown
; remaining to elapsed
; count
mov cs:,ax
; Time a zero - length code fragment, to get a reference for how
; much overhead this routine has. Time it 16 times and average it,
; for accuracy, rounding the result.
;
mov cs:,0
mov cx,16
cli ;interrupts off to allow a
; precise reference count
RefLoop:
call ReferenceZTimerOn
call ReferenceZTimerOff
loop RefLoop
sti
add cs:,8 ;total + (0.5 * 16)
mov cl,4
shr cs:,cl ;(total) / 16 + 0.5
;
; Restore original interrupt state.
;
pop ax ;retrieve flags when called
mov ch,cs: ;get back the original upper
; byte of the FLAGS register
and ch,not 0fdh ;only care about original
; interrupt flag...
and ah,0fdh ;...keep all other flags in
; their current condition
or ah,ch ;make flags word with original
; interrupt flag
push ax ;prepare flags to be popped
;
; Restore the context of the program being timed and return to it.
;
MPOPF ;restore the flags with the
; original interrupt state
pop cx
pop ax
ret
ZTimerOff endp
;
; Called by ZTimerOff to start timer for overhead measurements.
;
ReferenceZTimerOn proc near
;
; Save the context of the program being timed.
;
push ax
pushf ;interrupts are already off
;
; Set timer 0 of 8253 to mode 2 (divide - by - N), to cause
; linear counting rather than count - by - two counting.
;
mov al,00110100b ;set up to load
out MODE_8253,al ; initial timer count
DELAY
;
; Set the timer count to 0.
;
sub al,al
out TIMER_0_8253,al ;load count lsb
DELAY
out TIMER_0_8253,al ;load count msb
;
; Restore the context of the program being timed and return to it.
;
MPOPF
pop ax
ret
ReferenceZTimerOn endp
;
; Called by ZTimerOff to stop timer and add result to ReferenceCount
; for overhead measurements.
;
ReferenceZTimerOff proc near
;
; Save the context of the program being timed.
;
push ax
push cx
pushf
;
; Latch the count and read it.
;
mov al,00000000b ;latch timer 0
out MODE_8253,al
DELAY
in al,TIMER_0_8253 ;lsb
DELAY
mov ah,al
in al,TIMER_0_8253 ;msb
xchg ah,al
neg ax ;convert from countdown
; remaining to amount
; counted down
add cs:,ax
;
; Restore the context of the program being timed and return to it.
;
MPOPF
pop cx
pop ax
ret
ReferenceZTimerOff endp
;********************************************************************
;* Routine called to report timing results. *
;********************************************************************
ZTimerReport proc near
pushf
push ax
push bx
push cx
push dx
push si
push ds
;
push cs ;DOS functions require that DS point
pop ds ; to text to be displayed on the screen
assume ds:Code
;
; Check for timer 0 overflow.
;
cmp ,0
jz PrintGoodCount
mov dx,offset OverflowStr
mov ah,9
int 21h
jmp short EndZTimerReport
;
; Convert net count to decimal ASCII in microseconds.
;
PrintGoodCount:
mov ax,
sub ax,
mov si,offset ASCIICountEnd - 1
;
; Convert count to microseconds by multiplying by .8381.
;
mov dx,8381
mul dx
mov bx,10000
div bx ;* .8381 = * 8381 / 10000
;
; Convert time in microseconds to 5 decimal ASCII digits.
;
mov bx,10
mov cx,5
CTSLoop:
sub dx,dx
div bx
add dl,'0'
mov ,dl
dec si
loop CTSLoop
;
; Print the results.
;
mov ah,9
mov dx,offset OutputStr
int 21h
;
EndZTimerReport:
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
MPOPF
ret
ZTimerReport endp
Code ends
end
The following is the description of 8253 in the "Graphics Programmer's Guide", which is consistent with "Assembly Language, Design and Interface Technology":
The 8253 actually contains three timers, as shown in Figure 3.1. All three timers are driven by the system board's 14.31818 MHz crystal, divided by 12 to produce a 1.19318 MHz clock for the timers, so the timers count once every 838.1 ns. Each of the three timers counts down in a programmable way, generating a signal on its output pin when it counts down to 0. Each timer can be stopped at any time via a 0 level on its gate input; when a timer's gate input is 1, that timer counts continuously. In general, the 8253's timers are inherently very flexible timing devices; unfortunately, much of that flexibility depends on how the timers are connected to external circuits, and in the PC, the timers are connected for specific purposes.
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-3 14:27 |
|
|
jawbin
高级用户
   
积分 994
发帖 444
注册 2005-1-29
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
在通常的使用中,我就当是 18 次,没要求那么精密过. 可以设置成更高频率的( UCOS/II 好象就更改了),但是好象影响性能.
In normal use, I just take it as 18 times, and I haven't required such precision. It can be set to a higher frequency (UCOS/II seems to have changed it), but it seems to affect performance.
|
|
2006-6-8 19:29 |
|
|
fqljwdyq
新手上路

积分 14
发帖 7
注册 2006-2-18 来自 江苏
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
其实在实际应用当中,精确定时从来不用系统提供的8253,一般用扩展卡中的定时,对系统的这个18.2秒不是太关心
In actual applications, precise timing never uses the system-provided 8253. Generally, timing from expansion cards is used, and this 18.2 seconds of the system is not of much concern.
|
|
2006-6-9 08:15 |
|
|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第 6 楼』:
使用 LLM 解释/回答一下
但是我想在DOS下实现毫秒级定时啊!
是为了编动画、游戏程序
不可能希望别人装扩展卡
But I want to achieve millisecond-level timing under DOS!
It's for making animation and game programs
There's no hope of others installing expansion cards
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-9 09:02 |
|
|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第 7 楼』:
使用 LLM 解释/回答一下
我的目的是:编写类似Win32 API——QueryPerformanceFrequency、QueryPerformanceCounter——那样的函数来实现高精度计时
My purpose is: to write functions similar to the Win32 API - QueryPerformanceFrequency, QueryPerformanceCounter - to achieve high-precision timing
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-9 09:08 |
|
|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
菜菜的问一下:
TSC、ACPI是什么东西?
怎么利用它们来计时?
ACPI貌似是那个高级电源管理,它也有计时功能?昏,现在硬件接口资料真的好难找
http://blog.codingnow.com/2006/05/iaeeoeo.html
另外,Windows 下 QueryPerformanceCounter 是不可用的,这个根据 MSDN 的文档猜测,有可能是用 TSC 实现的。在多核和变频时代,TSC 几乎不可能取到准确的时间。
freebsd 上,使用 TSC 获取时间的优先级最低,现在一般使用 ACPI 获取时钟。在 Windows 上没有找到对应的手段。
Cai cai's question:
What are TSC and ACPI?
How to use them to time?
ACPI seems to be that advanced power management, does it also have a timing function? Oh, it's really hard to find hardware interface information now
http://blog.codingnow.com/2006/05/iaeeoeo.html
Also, QueryPerformanceCounter in Windows is not available. According to the MSDN documentation, it is guessed that it may be implemented using TSC. In the multi-core and variable frequency era, it is almost impossible to get accurate time with TSC.
On freebsd, the priority of using TSC to get time is the lowest. Now generally use ACPI to get the clock. No corresponding means are found in Windows.
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-9 09:14 |
|
|
asbai
高级用户
   
积分 653
发帖 252
注册 2006-4-16
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
TSC是奔腾及以上处理器新增的一个64bit的register,在每个CPU基础时钟,该计数器会自动增一(基础时钟是指:流水的stage)。TSC可以使用RDTSC指令读取。
Win32API 中的 QueryPerformanceCounter 确实应该是使用了 TSC,一是它的精度很高,二是MSDN也说了这个API使用了某些硬件相关的特性,在一些CPU上可能不支持。
TSC主要的设计用意是 profiling,在大多数情况下,用它做计时是不合适的,主要是开销较高。
大多数情况下,8253本身最高可以工作在纳秒级的精度上。这个精度对于绝大部分应用来说应该是足够了,但是包括Windows在内的任何操作系统通常不可能让自己的工作粒度保持在这个频率,这会使操作系统本身的维护性开销过大。
再加上Windows处理中断的时候,为了进一步降低开销,还专门使用了DPC机制,所以NT系列的Windows客户端产品的Timer粒度一般在10ms~15ms,服务器产品的粒度一般在15ms~30ms。
通过Windows Native API(不是Win32 API):NtSetTimerResolution,可以改变系统的工作粒度。不过,这个改变会影响当前系统的所有进程,而且不恰当的设置可能会增加系统的管理负担。
更为不爽的是,有迹向表明这个设置很可能也影响系统内核的工作状态,例如:线程调度、阻塞事件和异步IO状态查询等等,调整这个值也相应的增加了这些工作的频率,导致系统性能进一步下滑。
TSC is a newly added 64-bit register in Pentium and above processors. This counter increments by one automatically at each CPU base clock (the base clock refers to the stage of the pipeline). TSC can be read using the RDTSC instruction.
The QueryPerformanceCounter in the Win32 API indeed should use TSC. First, its precision is very high. Second, MSDN says that this API uses some hardware-related features, and it may not be supported on some CPUs.
The main design intention of TSC is profiling. In most cases, it is not suitable to use it for timing, mainly because the overhead is relatively high.
In most cases, the 8253 itself can work at a precision of the nanosecond level at most. This precision should be sufficient for most applications, but any operating system including Windows usually cannot keep its own working granularity at this frequency, which would make the maintenance overhead of the operating system itself too large.
Plus, when Windows handles interrupts, in order to further reduce the overhead, it specially uses the DPC mechanism. So the Timer granularity of NT-series Windows client products is generally between 10ms and 15ms, and the granularity of server products is generally between 15ms and 30ms.
Through the Windows Native API (not the Win32 API): NtSetTimerResolution, the working granularity of the system can be changed. However, this change will affect all processes in the current system, and improper settings may increase the management burden of the system.
What is even more frustrating is that there are signs that this setting may also affect the working state of the system kernel, such as thread scheduling, blocked event and asynchronous IO state query, etc. Adjusting this value also correspondingly increases the frequency of these tasks, leading to further performance degradation of the system.
|
|
2006-6-9 13:05 |
|
|
asbai
高级用户
   
积分 653
发帖 252
注册 2006-4-16
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
ACPI?
zyl910兄是想说Advanced Programmable Interrupt Controller (APIC) Timer?
至于一般说的ACPI Timer,就是RTC在ACPI兼容的系统中引发的周期性计时中断。
Microsoft的硬件开发中心有一篇专门介绍各种硬件Timer和计时问题的文章:
http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx
ACPI?
Brother zyl910 is referring to the Advanced Programmable Interrupt Controller (APIC) Timer?
As for the commonly said ACPI Timer, it is the periodic timing interrupt triggered by the RTC in an ACPI-compliant system.
There is a special article on various hardware Timers and timing issues introduced by Microsoft's Hardware Development Center:
http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx
|
|
2006-6-9 13:14 |
|
|
zyl910
中级用户
  
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第 11 楼』:
使用 LLM 解释/回答一下
昏
原来TSC是指RDTSC
平时没注意其缩写
非常感谢asbai兄
现在硬件接口编程资料真的好难找
想在DOS下编写一个精确点的计时函数都好麻烦
昏
Original TSC refers to RDTSC. I didn't pay attention to its abbreviation usually.
Thanks a lot, brother asbai. Now it's really hard to find hardware interface programming materials. It's quite troublesome to write a more accurate timing function under DOS.
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-6-10 12:56 |
|
|
asbai
高级用户
   
积分 653
发帖 252
注册 2006-4-16
状态 离线
|
『第 12 楼』:
使用 LLM 解释/回答一下
Originally posted by zyl910 at 2006-6-10 12:56:
昏
原来TSC是指RDTSC
平时没注意其缩写
非常感谢asbai兄
现在硬件接口编程资料真的好难找
想在DOS下编写一个精确点的计时函数都好麻烦
zyl910兄太客气了,现在硬件资料确实不好找,Intel和AMD发布的x86开发者手册既权威又详细(特别是AMD的),应该是首选资料来源。其它的还有一个网站: http://www.powernet.co.za/info/index.htm,速度虽然慢点,但是资料蛮全的。
俺就知道这么多了,各位兄台有什么好去处,拿出来share一下。<img src="images/smilies/face-smile-big.png" align="absmiddle" border="0">
Originally posted by zyl910 at 2006-6-10 12:
Dizzy
It turns out that TSC refers to RDTSC
I didn't pay attention to its abbreviation at ordinary times
Thank you very much, Brother asbai
Now, hardware interface programming materials are really hard to find
It's so troublesome to write a more accurate timing function under DOS
Brother zyl910, you're too polite. Now, hardware materials are really hard to find. Intel and AMD released x86 developer manuals are both authoritative and detailed (especially AMD), which should be the preferred source. There is also a website: http://www.powernet.co.za/info/index.htm, although the speed is a bit slow, the materials are quite complete.
I only know so much. Brothers, do you have any good places, take them out and share them. :D
|
|
2006-6-10 14:16 |
|
|