Page 1 of 1
8254 chip
Posted: Fri Apr 15, 2005 5:30 am
by DruG5t0r3
I'm trying to change the rate of the 8254 chip to make an interrupt every 100 seconds...well it doesn't work...it actually creates an interrupt at least 500+ times per sec. See anything wrong with this code?
Code: Select all
#define I8254_PORT 0x40
#define I8254_PORT1 0x41
#define I8254_CTRL 0x43
#define MAX_CLOCK 1193180
void set_clock_i386(u16 frequency) {
if (frequency == 0)
return;
u16 ticks = MAX_CLOCK / frequency;
outportb(I8254_CTRL, 0x34);
outportb(I8254_PORT, ticks % 256); // LSB counter
outportb(I8254_PORT, ticks / 256); // MSB counter
return;
}
Re:8254 chip
Posted: Fri Apr 15, 2005 6:08 am
by Pype.Clicker
we may have different needs, but i used to set control word to 0x43 rather than 0x34.
Also, you need to know that emulators such as bochs or qemu are *not* reliable concerning time. Their clock is typically way faster than the 'real' clock ...
Re:8254 chip
Posted: Fri Apr 15, 2005 6:49 am
by Brendan
Hi,
Pype.Clicker wrote:
we may have different needs, but i used to set control word to 0x43 rather than 0x34.
Pype: You might want to double check that (perhaps confused with IO Port 0x43?)...
For 0x34 you end up with:
- channel 0
- lobyte/hibyte
- mode 2 (rate generator)
- binary
For 0x43 you end up with:
- channel 1
- counter latch
- mode 1 (hardware-retriggerable one-shot)
- BCD
IMHO "outportb(I8254_CTRL, 0x34);" is probably entirely correct.
That said, I've never trusted compilers when it comes to the order they convert variable sizes. For example, for "u16 ticks = MAX_CLOCK / frequency" does the compiler convert MAX_CLOCK and frequency to 16 bits
before doing the division, or does it do a 32 bit division and convert it to 16 bits
after? It's probably just my own lack of C knowlege (and the fact that I can't think of anything else wrong with the code), but no harm done if I'm chasing shadows right?
...
Cheers,
Brendan
Re:8254 chip
Posted: Fri Apr 15, 2005 7:01 am
by DruG5t0r3
That said, I've never trusted compilers when it comes to the order they convert variable sizes. For example, for "u16 ticks = MAX_CLOCK / frequency" does the compiler convert MAX_CLOCK and frequency to 16 bits before doing the division, or does it do a 32 bit division and convert it to 16 bits after?
I've tested that and it actually calculates the correct value.
Clicker : Well then if bochs runs its clock way faster than a normal one...how would you accurately calculate time?
Re:8254 chip
Posted: Fri Apr 15, 2005 7:13 am
by bubach
Test it on a real PC and ignore BOCHS?
My delay function says that 5sec has passed in about 2 seconds in BOCHS, and i don't care.
Re:8254 chip
Posted: Fri Apr 15, 2005 7:22 am
by Pype.Clicker
Pype.Clicker wrote:
we may have different needs, but i used to set control word to 0x43 rather than 0x34.
Pype: You might want to double check that (perhaps confused with IO Port 0x43?)...
ooooooh ... my my ...
Still being dazzled by that *silly* convention OUT(VALUE,PORT) of mine in Clicker ... i *really* need to change that .
btw, i'm using mode 0x36 (looking up docs: that's "square wave rate generator" instead of "wave generator")
Well then if bochs runs its clock way faster than a normal one...how would you accurately calculate time?
you can't (unless you found bochs/linux combination that is more accurate). Timing within the virtual machine will however remain accurate compared to the rest of the virtual hardware (virtual floppy, virtual disks, etc), but it shouldn't be expected to be synchronized with the clock-wall time in any way.
Re:8254 chip
Posted: Fri Apr 15, 2005 7:31 am
by Brendan
Hi,
You can't reliably make any of the timers in Bochs accurate, but you can improve the accuracy. First I'd compile with the "--enable-new-pit" option. Then (most importantly) you need to set the IPS setting (in the bochsrc.txt" file) correctly.
To do this, compile Bochs with the "--enable-show-ips" option, set the "ips: 123456" line in "bochsrc.txt" to the IPS value it showed, and then compile it again without the "--enable-show-ips" option.
It still won't be perfect, and any other adjustment (for e.g. changing the "vga_update_interval, CPU family, etc) might mess it up, but it's about as good as you'll get.
In any event, you should probably run your OS on a real computer occasionally (no emulator is perfect).
@Pype: Square wave is just as good, you just need to remember that the output frequency is halved
.
Cheers,
Brendan
Re:8254 chip
Posted: Fri Apr 15, 2005 7:37 am
by Solar
Brendan wrote:
I've never trusted compilers when it comes to the order they convert variable sizes. For example, for "u16 ticks = MAX_CLOCK / frequency" does the compiler convert MAX_CLOCK and frequency to 16 bits before doing the division, or does it do a 32 bit division and convert it to 16 bits after?
When doing arithmetics on two variables of different sizes, the smaller one is extended to the size of the larger one before the operation is carried out. Only in assignment or explicit cast does a variable get truncated.
In the example, frequency will get extended to the size of MAX_CLOCK, the division being made, and the result (which is of the size of MAX_CLOCK) assigned to ticks (which implicitly downcasts it to u16).
HTH.
Re:8254 chip
Posted: Fri Apr 15, 2005 7:49 am
by Brendan
Hi,
Solar wrote:When doing arithmetics on two variables of different sizes, the smaller one is extended to the size of the larger one before the operation is carried out. Only in assignment or explicit cast does a variable get truncated.
This is what should happen, but I (vaguely) remember running into problems with "long long = int * int" in GCC. It's highly likely it was my fault rather than the compiler's though.
Assembly programmers like me tend to prefer things to be explicitly defined rather than determined via. implicit rules
.
Cheers,
Brendan
Re:8254 chip
Posted: Fri Apr 15, 2005 7:57 am
by Solar
Brendan wrote:
This is what should happen, but I (vaguely) remember running into problems with "long long = int * int" in GCC. It's highly likely it was my fault rather than the compiler's though.
Should you happen to find that "bug" again, I'd like to hear about it.
Assembly programmers like me tend to prefer things to be explicitly defined rather than determined via. implicit rules
.
I
could start a rant against NASM syntax at this point and why I prefer GAS, but I won't.
Re:8254 chip
Posted: Fri Apr 15, 2005 6:41 pm
by DruG5t0r3
To do this, compile Bochs with the "--enable-show-ips" option, set the "ips: 123456" line in "bochsrc.txt" to the IPS value it showed, and then compile it again without the "--enable-show-ips" option.
Thanks! that works