LowLevel
05.05.2022, 11:11 |
modern timers in DOS (32bit) (Developers) |
Hi @ all,
I would like to use a modern timer in DOS (to be able to get a 5-10kHz timer interrupt), I know that I have to dig into ACPI ,... and I´m not sure if it is possible anyway,...
Before I try it, has anybody used a modern timer or does know a library which a could try/study ?!?!
I´m using open watcom c/c++ ,...
THX´s LowLevel |
bretjohn
Rio Rancho, NM, 05.05.2022, 19:05
@ LowLevel
|
modern timers in DOS (32bit) |
> Hi @ all,
>
> I would like to use a modern timer in DOS (to be able to get a 5-10kHz
> timer interrupt), I know that I have to dig into ACPI ,... and I´m not
> sure if it is possible anyway,...
>
> Before I try it, has anybody used a modern timer or does know a library
> which a could try/study ?!?!
>
> I´m using open watcom c/c++ ,...
>
> THX´s LowLevel
You'll need to explain what you mean by "modern timer", and a little more detail in exactly what you mean by "timer". If you're wanting the computer to generate an interrupt at some specific frequency, there are ways to do it that don't involve ACPI. Keep in mind that the frequency of interrupts on a PC is not precise since they involve a mixture of hardware and software.
If you're just wanting to "monitor" the frequency and don't require hardware notifications (interrupts) at each tick of the clock, that can use a different approach. |
mceric
Germany, 05.05.2022, 20:53
@ bretjohn
|
modern timers in DOS (32bit) |
> > I would like to use a modern timer in DOS (to be able to get a 5-10kHz
> > timer interrupt), I know that I have to dig into ACPI
No you do not. If you do not spend too much CPU time in your handler, even ancient 386 already allowed you to create timer interrupts at a rate of many 1000 per second, using the classic https://en.wikipedia.org/wiki/Intel_8253 chip. This was used in audio players for people without sound cards
Actually 18.2 Hz is the SLOWEST possible speed (1.19MHz / 64k) which is used by the BIOS to use as little CPU time for wall clock updates as possible. Everybody is free to change to a different speed as long as they take care of keeping the 40:6c clock run at the same speed, for example by only calling the original int 8 handler once for one in every X interrupts generated by the 8253. There are plenty of tutorials for such things from the 1990s
You can also use the RTC timer interrupt or ask the BIOS to wait for N microseconds. The latter is usually implemented by the BIOS activating a 1024 Hz RTC interrupt, but you can also get 2 Hz and 8192 Hz RTC interrupt rates.
The nice thing about using RTC interrupt 0x70 is that it is independent from int 0x08 and int 0x1c, so you do not have to worry about whether and how often to call previous interrupt 0x08 handlers. You will probably have the RTC interrupt all for yourself on many systems, it is not widely used otherwise.
The disadvantage is that you only have a choice of 2, 1024 or 8192 Hz. If you want more flexibility, use good old 8253 int 8, which can have any frequency between 18.2 Hz and 0.6 MHz, but you better limit yourself to 1/10 or 1/100 of that to avoid wasting too much CPU time. On a 386, even 10 kHz already means a significant CPU load even with optimized handler code.
Of course, if you feel masochistic, you could use modern timers such as HPET or similar. Modern computers are likely to even contain various extra microcontrollers for maintenance stuff or I/O interfaces. Who knows what sorts of abuse can be implemented using those :-p
If you only want to measure time in a very fine-grained way, use the TSC. Every Intel CPU since at least Pentium had a time stamp counter and most other brands introduced one not much later. The time stamps typically have a very high resolution, for example CPU clock cycles, and processors may even compensate the counts for you when changing clock speeds in power saving modes. TSC is easy to use, you just need a little helper to fetch the value, usually written in Assembly.
More DOS-friendly C compilers may already have the helper prepared for you. Protected mode OS may not let you access the real counter, so I guess your mileage may vary with a DOS application running in Windows. But that would certainly not let you manipulate HPET or ACPI stuff either. I wonder whether Windows offers a simulated 8253 to DOS boxes, does anybody know? In any case, before using RDTSC, make sure that you can actually access it.
https://www.felixcloutier.com/x86/rdtsc --- FreeDOS / DOSEMU2 / ... |
Laaca
Czech republic, 05.05.2022, 20:56
@ LowLevel
|
modern timers in DOS (32bit) |
Few weeks ago I announced a update of my tool ACPITOOL.
The new feature is the detection and access to the modern ACPI timer running at frequency 3,5MHz
http://www.bttr-software.de/forum/forum_entry.php?...p;page=0&category=all&order=last_answer --- DOS-u-akbar! |
Japheth
Germany (South), 06.05.2022, 08:06
@ mceric
|
modern timers in DOS (32bit) |
Absolutely true!
> If you only want to measure time in a very fine-grained way, use the TSC.
> Every Intel CPU since at least Pentium had a time stamp counter and most
> other brands introduced one not much later. The time stamps typically have
> a very high resolution, for example CPU clock cycles, and processors may
> even compensate the counts for you when changing clock speeds in power
> saving modes.
If you need a resolution of 0.1 to 1 ms, just use the normal, unmodified int 8 timer and read the values of the timer at the events you are interested in. Here's my standard code:
;--- this returns timer value in ms
GetTimerValue proc uses es bx
mov es, [_0000H]
tryagain:
mov edx,es:[46ch]
mov al,0C2h ;read timer 0 status + value low/high
out 43h, al
xchg edx, edx
in al,40h
mov cl,al ;CL = status
xchg edx, edx
in al,40h
mov ah, al ;AH = value low
xchg edx, edx
in al,40h ;AL = value high
test cl,40h ;was latch valid?
jnz tryagain
cmp edx,es:[46ch] ;did an interrupt occur in the meantime?
jnz tryagain ;then do it again!
xchg al,ah
;--- usually (counter mode 3) the timer is set to count down *twice*!
;--- however, sometimes counter mode 2 is set!
mov ch,cl
and ch,0110B ;bit 1+2 relevant
cmp ch,0110B ;counter mode 3?
jnz @F
;--- in mode 3, PIN status of OUT0 will become bit 15
shr ax,1
and cl,80h
or ah, cl
@@:
;--- now the counter is in AX (counts from FFFF to 0000)
neg ax
;--- now the count is from 0 to FFFF
ret
GetTimerValue endp
;--- get timer value in ms in eax
gettimer proc
call GetTimerValue
;--- the timer ticks are in EDX:AX, timer counts down
;--- a 16bit value with 1,193,180 Hz -> 1193180/65536 = 18.20648 Hz
;--- which are 54.83 ms
;--- to convert in ms:
;--- 1. subticks in ms: AX / 1193
;--- 2. ticks in ms: EDX * 55
;--- 3. total 1+2
push edx
movzx eax,ax ;step 1
cdq
mov ecx, 1193
div ecx
mov ecx, eax
pop eax ;step 2
mov edx, 55
mul edx
add eax, ecx ;step 3
ret
gettimer endp
--- MS-DOS forever! |
LowLevel
06.05.2022, 08:08
@ bretjohn
|
modern timers in DOS (32bit) |
Hi bretjohn,
fist of all I have to say I´m not an OS developer ,.. I´m coding just for fun and I want to expand my knowledge,...
> You'll need to explain what you mean by "modern timer", and a little more
> detail in exactly what you mean by "timer". If you're wanting the computer
> to generate an interrupt at some specific frequency, there are ways to do
> it that don't involve ACPI. Keep in mind that the frequency of interrupts
> on a PC is not precise since they involve a mixture of hardware and
> software.
I´m thinking of a lapic timer or perhaps the hpet, and yes I would like to generate interrupts at a specific frequency. I fully understand that on a PC the timer interrupts are not that precise than on other "platforms".
> If you're just wanting to "monitor" the frequency and don't require
> hardware notifications (interrupts) at each tick of the clock, that can use
> a different approach.
You are thinking of the time stamp counter or ?
Thank for very much for your explainations and inputs!
cheers LowLevel |
LowLevel
06.05.2022, 08:29
@ mceric
|
modern timers in DOS (32bit) |
Hi mceric,
> No you do not. If you do not spend too much CPU time in your handler, even
> ancient 386 already allowed you to create timer interrupts at a rate of
> many 1000 per second, using the classic
> https://en.wikipedia.org/wiki/Intel_8253 chip. This was used in audio
> players for people without sound cards
>
> Actually 18.2 Hz is the SLOWEST possible speed (1.19MHz / 64k) which is
> used by the BIOS to use as little CPU time for wall clock updates as
> possible. Everybody is free to change to a different speed as long as they
> take care of keeping the 40:6c clock run at the same speed, for example by
> only calling the original int 8 handler once for one in every X interrupts
> generated by the 8253. There are plenty of tutorials for such things from
> the 1990s
Hmmm,... that´s exactly what I tried, but unfortunately I was not able to get more than 1024Hz,...I will do some more investigations on that - maybe its because I use a mainboard which "simulates" the old 8253,...
> You can also use the RTC timer interrupt or ask the BIOS to wait for N
> microseconds. The latter is usually implemented by the BIOS activating a
> 1024 Hz RTC interrupt, but you can also get 2 Hz and 8192 Hz RTC interrupt
> rates.
>
> The nice thing about using RTC interrupt 0x70 is that it is independent
> from int 0x08 and int 0x1c, so you do not have to worry about whether and
> how often to call previous interrupt 0x08 handlers. You will probably have
> the RTC interrupt all for yourself on many systems, it is not widely used
> otherwise.
> The disadvantage is that you only have a choice of 2, 1024 or 8192 Hz. If
> you want more flexibility, use good old 8253 int 8, which can have any
> frequency between 18.2 Hz and 0.6 MHz, but you better limit yourself to
> 1/10 or 1/100 of that to avoid wasting too much CPU time. On a 386, even 10
> kHz already means a significant CPU load even with optimized handler code.
I will try it too, THX´s for the hint!
> Of course, if you feel masochistic, you could use modern timers such as
> HPET or similar. Modern computers are likely to even contain various extra
> microcontrollers for maintenance stuff or I/O interfaces. Who knows what
> sorts of abuse can be implemented using those :-p
masochistic ,... hahahaha,.. ;)
> If you only want to measure time in a very fine-grained way, use the TSC.
> Every Intel CPU since at least Pentium had a time stamp counter and most
> other brands introduced one not much later. The time stamps typically have
> a very high resolution, for example CPU clock cycles, and processors may
> even compensate the counts for you when changing clock speeds in power
> saving modes. TSC is easy to use, you just need a little helper to fetch
> the value, usually written in Assembly.
I know!
> More DOS-friendly C compilers may already have the helper prepared for you.
> Protected mode OS may not let you access the real counter, so I guess your
> mileage may vary with a DOS application running in Windows. But that would
> certainly not let you manipulate HPET or ACPI stuff either. I wonder
> whether Windows offers a simulated 8253 to DOS boxes, does anybody know? In
> any case, before using RDTSC, make sure that you can actually access it.
> https://www.felixcloutier.com/x86/rdtsc
I want to run my programs just in DOS! My next challenge is to check if I can access the hpet, lapic timer ,.. thru a dos extender with a high frequency ,... I´m not sure at the moment.
THX´s for your time to reply !!!
LowLevel |
LowLevel
06.05.2022, 08:30
@ Laaca
|
modern timers in DOS (32bit) |
hi Laaca,
> Few weeks ago I announced a update of my tool ACPITOOL.
> The new feature is the detection and access to the modern ACPI timer
> running at frequency 3,5MHz
> http://www.bttr-software.de/forum/forum_entry.php?...p;page=0&category=all&order=last_answer
ohhh man, that sounds great!!! I have to try it!!!!
cheers LowLevel |
LowLevel
06.05.2022, 08:37
@ Japheth
|
modern timers in DOS (32bit) |
Hi Japheth!
> Absolutely true!
>
> > If you only want to measure time in a very fine-grained way, use the
> TSC.
> > Every Intel CPU since at least Pentium had a time stamp counter and most
> > other brands introduced one not much later. The time stamps typically
> have
> > a very high resolution, for example CPU clock cycles, and processors may
> > even compensate the counts for you when changing clock speeds in power
> > saving modes.
>
> If you need a resolution of 0.1 to 1 ms, just use the normal, unmodified
> int 8 timer and read the values of the timer at the events you are
> interested in. Here's my standard code:
>
I mentioned it in another reply ,... I couldn´t get more than 1024Hz (with my code)
I will test your code!
Thanks for your code snippet!
Low Level
ps: I´m new in this forum, and I´m really surprised how many answers and hints I got in one day from all of you !!! Didn´t expect that,...awesome!!! |
bretjohn
Rio Rancho, NM, 06.05.2022, 20:01
@ LowLevel
|
modern timers in DOS (32bit) |
> I´m thinking of a lapic timer or perhaps the hpet, and yes I would like to
> generate interrupts at a specific frequency. I fully understand that on a
> PC the timer interrupts are not that precise than on other "platforms".
Those kinds of timers can indeed be used to generate interrupts. For experimental/private purposes that can be OK, but since they only exist on some computers (they are not very "universal") I personally wouldn't normally use them. As others have indicated, they may not even work (at least correctly) in at least some Virtual Machines.
What I normally use is the RTC (IRQ 8/INT 70h) which is programmable through the CMOS. It is programmable to generate interrupts from 2 Hz up to 8192 Hz in factors of 2^n (2, 4, 8, 16, ...) with the default of 1024 Hz. As mceric indicated, it's not used by too many programs so you can reprogram it to something other than 1024. I would still avoid reprogramming it, though. I use it in some of my programs and even though it would be "nice" to reprogram it I don't because of the potential issues it CAN cause when the program is not in complete control of everything. That's also why I never reprogram the PIC timer for IRQ 0 (INT 8).
>> If you're just wanting to "monitor" the frequency and don't require
>> hardware notifications (interrupts) at each tick of the clock, that can
>. use a different approach.
>
> You are thinking of the time stamp counter or ?
The TSC is one way, but again that's less "universal" than using something like the PIC counter (which is what Japheth's code uses). The PIC counter has a resolution of about a microsecond, which is more than sufficient for most applications.
There are also"tricks " you can play with things like USB host controllers. The USB bus has its own "ecosystem" and timers and you can sometimes tap into those timers if you're careful. You really can't use the USB host hardware to generate interrupts "on demand" (though my USB drivers have an "extension" that allows you to do it). But you can use the USB hardware to "monitor" time durations. |
tkchia
08.05.2022, 17:57
@ bretjohn
|
modern timers in DOS (32bit) |
Hello bretjohn,
> There are also"tricks " you can play with things like USB host controllers.
> The USB bus has its own "ecosystem" and timers and you can sometimes tap
> into those timers if you're careful. You really can't use the USB host
> hardware to generate interrupts "on demand" (though my USB drivers have an
> "extension" that allows you to do it). But you can use the USB hardware to
> "monitor" time durations.
Me, I am still trying to work out how to interact with a USB XHCI or EHCI controller (whichever comes first) in a useful way...
Thank you! --- https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI" |
RayeR
CZ, 18.05.2022, 22:40
@ mceric
|
modern timers in DOS (32bit) |
TSC should be mostly accessible also under pmode OSes (not privileged level required). But maybe after Spectre/Meltdown bugs was revealed some OSes might changed policy to not alow user read TSC anymore (disable the bit) :\
Also TSC may have some quirks like it may depend on current CPU multiplier or clock modulation, the behavior has changed during CPU generations. Also under multicore OS without setting the affinity to a single core your program may read TSC of a different CPU core that may be desynchronized due to dynamic multiplier changing and core parking everytime and you end with a insane time difference...
Also modern CPUs has some performance counters but I never tried them.
And finally some warning that CPU may spend some random time inside SMI handler that has higher pririty over any common INT and you don't have control over it so don't rely with a PC on generating precise timing waveforms, for such case use some dedicated microcontroller... --- DOS gives me freedom to unlimited HW access. |