能力值:
( LV2,RANK:10 )
2 楼
怎么没人回复啊,我要悲剧了。。。
能力值:
( LV2,RANK:10 )
3 楼
已解决,哈哈!
能力值:
( LV2,RANK:10 )
4 楼
怎么解决的?共享下吧。
能力值:
( LV2,RANK:10 )
5 楼
你都已经解决了我再回帖是不是很招人鄙视。。。简单说一下我的理解吧。
8254的三个通道的时钟输入CLK不是CPU输出的CLK,而是PCLK,频率大概是1.19318MHz,通道0就是用于系统计时的,初始化代码如下:
mov al, 36h
out 43h, al
mov al, 0
out 40h, al
out 40h, al
首先向43h端口发送数据36h,这个端口是8254的方式控制寄存器,格式如下:
│7│6│5│4│3│2│1│0│ Mode Control Register
│ │ │ │ │ │ │ └──── 0=16 binary counter, 1=4 decade BCD counter
│ │ │ │ └ ┴ ─┴───── counter mode bits
│ │ └─┴────────── read/write/latch format bits
└─┴───────────── counter select bits (also 8254 read back command)
所以36h的含义是,计数器选择的是计时器0、写16位计数器、方式3、格式是二进制,方式3指的是OUT端输出方波,当设置了要计数的值之后,在下一个CLK下降沿就开始递减计数,然后向40h即通道0送了两个数据0,因为是递减计数,所以其实数据应该是2^16=65536,显然是在计时65536个PCLK,65536 * 1 / 1.19318MHz = 0.054925……,大概55ms,用于计时24小时的话会有误差,所以在主8259的IR0中断例程中修正了0B0h个PCLK……
结合这一个再看一下8254通道1的设置就可以了,通道1是用于系统刷新DRAM的,假设刷新时间为15微秒,初始化例程就像下面这样写:
mov al, 54h
out 43h, al
mov al, 12h
out 41h, al
18 * 1 / 1.19318MHz = 15.086 微秒....
能力值:
( LV2,RANK:10 )
6 楼
5楼分析的我已试过,只修改它的话在当前多核系统下是没有用的,因为多核系统下,8254连接到IOAPIC中的IRQ2,我打印出它的中断重定向表的64位重定向表项是:0x100FF(低32位),0x6F000000(高32位),第17位为1表示此中断是屏蔽的,所以我之前修改8254的通道一的计数寄存器是没有效果的。在IOAPIC中时钟中断对应的是IRQ8,我打印出它对应的64位重定性表项是:0x8D1(低32位),0x1000000(高32位,它的高8位为1表示只把时钟中断发给主CPU,然后)。所以我把IRQ8的64位重定向表copy到IRQ2中,然后把IRQ8对应的屏蔽位(第十七位)置为1,这样就屏蔽了原来的时钟中断。设置好上述两个重定向表项,然后对8254进行编程即可实现任意时钟周期。
试验中,我把时钟周期由原来的15ms改为1ms后,前端的界面那些小动画忽忽的闪啊,而且双击基本用不了了(必须点的足够块才有双击效果
)。玩dota时,有点小问题,显示我开始游戏后就秒了,悲剧啊。通过上述观察,已基本确定时钟频率已修改。但是目前我还没有找到一种能通过正规的编程来验证它,正在寻觅中,有哪位达人有什么好想法然后告诉我,先在此拜谢
能力值:
( LV2,RANK:10 )
7 楼
IOAPIC没接触过,只在DOS下对8254编过程,建议翻一下BIOS代码看有帮助没,也或许是OS的原因?
PS:IOAPIC指的是82093AA么?Intel有它的手册可以下载,或许有帮助:http://www.intel.com/design/chipsets/datashts/29056601.pdf