8254 chip

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
DruG5t0r3

8254 chip

Post 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;
}
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:8254 chip

Post 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 ...
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:8254 chip

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
DruG5t0r3

Re:8254 chip

Post 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?
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:8254 chip

Post 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. ;)
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:8254 chip

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:8254 chip

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:8254 chip

Post 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.
Every good solution is obvious once you've found it.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:8254 chip

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:8254 chip

Post 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. :-D
Every good solution is obvious once you've found it.
DruG5t0r3

Re:8254 chip

Post 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
Post Reply