OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Mar 19, 2024 4:25 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: apic timer
PostPosted: Thu Jul 14, 2005 10:48 pm 
I'm working on some apic code right now and I'm trying to figure out how you can get the apic to fire off an interrupt every lets say...1 seconds. Based on the Intel book, says the timer is derived from the cpu bus clock speed. So how can you effectively set the apic to interrupt every second?


Top
  
 
 Post subject: Re:apic timer
PostPosted: Fri Jul 15, 2005 12:43 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

DruG5t0r3 wrote:
I'm working on some apic code right now and I'm trying to figure out how you can get the apic to fire off an interrupt every lets say...1 seconds. Based on the Intel book, says the timer is derived from the cpu bus clock speed. So how can you effectively set the apic to interrupt every second?


First (assuming the local APIC is enabled and ready), you have to find out how quick the CPU's bus speed is. Then you set the APIC timer divider and APIC timer count to values that are calculated from the measured bus speed.

To measure the CPU's bus speed you'd see how many times the APIC timer's count is decreased over a fixed time delay. After that it's fairly easy. For example:

Code:
%define LAPICapicID         0x0020+LAPIC_BASE_ADDRESS
%define LAPICversion         0x0030+LAPIC_BASE_ADDRESS
%define LAPICtaskPriority      0x0080+LAPIC_BASE_ADDRESS
%define LAPICendOfInterrupt      0x00B0+LAPIC_BASE_ADDRESS
%define LAPIClogicalDestination      0x00D0+LAPIC_BASE_ADDRESS
%define LAPICdestinationFormat      0x00E0+LAPIC_BASE_ADDRESS
%define LAPICspurious         0x00F0+LAPIC_BASE_ADDRESS
%define LAPICinterruptCommandLow   0x0300+LAPIC_BASE_ADDRESS
%define LAPICinterruptCommandHigh   0x0310+LAPIC_BASE_ADDRESS
%define LAPICLVTtimer         0x0320+LAPIC_BASE_ADDRESS
%define LAPICLVTperfCounter      0x0340+LAPIC_BASE_ADDRESS
%define LAPICLVT_LINT0         0x0350+LAPIC_BASE_ADDRESS
%define LAPICLVT_LINT1         0x0360+LAPIC_BASE_ADDRESS
%define LAPICLVTerror         0x0370+LAPIC_BASE_ADDRESS
%define LAPICTIMERinitialCount      0x0380+LAPIC_BASE_ADDRESS
%define LAPICTIMERcurrentCount      0x0390+LAPIC_BASE_ADDRESS
%define LAPICTIMERdivider      0x03E0+LAPIC_BASE_ADDRESS

%define LTIMERdivideBy1         0x0000000B
%define LTIMERdivideBy16      0x00000003
%define LTIMERdivideBy128      0x0000000A

%define LTIMERperiodic          0x00020000



get_bus_speed:

;Install the IRQ handler for the local APIC timer

   mov edi,LAPIC_timer_IRQ_handler
   mov al,LAPIC_int_vector
   call create_IDT_descriptor

;Tell the local APIC to use the LAPIC_int_vector, set it to "one-shot" mode and enable it

   mov dword [LAPICLVTtimer],LAPIC_int_vector

;Set the local APIC timer divider to divide by 128

   mov dword [LAPICTIMERdivider],LTIMERdivideBy128

;Configure the RTC or PIT timer for an IRQ every 250 mS (4 Hz)
; Note: The handler for this timer's IRQ just does "inc dword [value]"

   call configure_RTC_or_PIT

;Wait for the start of the next RTC or PIT IRQ

   mov eax,[value]
.wait1:
   cmp [value],eax
   je .wait1:

;Set the initial count to 0xFFFFFFFF, which starts the local APIC timer

   mov dword [LAPICTIMERinitialCount],0xFFFFFFFF

;Wait for the next RTC or PIT IRQ

   mov eax,[value]
.wait2:
   cmp [value],eax
   je .wait2:

;Stop the local APIC timer

   mov [LAPICLVTtimer],LVTdisabled

;Read the local APIC timer count

   mov ebx,[LAPICTIMERcurrentCount]

;Stop the PIT or RTC timer

   call stop_RTC_or_PIT

;Work out how much the local APIC timer's count decreased

   mov eax,0xFFFFFFFF     ;eax = initial value used
   sub eax,ebx                     ;eax = number of times it changed

;Calculate the CPU's bus frequency (Hz) in EDX:EAX

   mov ebx,(128 / 4)
   mul ebx

;Calculate the local APIC count for the frequency you want

   mov ebx,FREQUENCY
   div ebx

;Adjust it for a different local APIC timer divider

   xor edx,edx
   mov ebx,16
   div ebx

;Set the new local APIC timer divider

   mov dword [LAPICTIMERdivider],LTIMERdivideBy16

;Set the new local APIC timer count

   mov [LAPICTIMERinitialCount],eax

;And then enable the local APIC timer in "periodic" mode and return

   mov dword [LAPICLVTtimer], LAPIC_int_vector | LTIMERperiodic
   ret


You'll also want something like:

Code:
LAPIC_timer_IRQ_handler:
   mov dword [LAPICendOfInterrupt],0   ;Send the EOI
   iretd


Depending on the duration of the fixed time value and the local APIC timer frequency you actually want, you may want to adjust the values used for the local APIC timer divider. I'd select timer divider values to get the best accuracy while preventing overflows (e.g. so it works up to 1 GHz bus frequency - nothing wrong with future-proofing). You might also want to play with how long the duration of the fixed time value is - 250 mS is relatively long considering the speed of even the slowest CPU's bus.

BTW for a frequency of 1 Hz it'd probably be better to use the RTC timer instead, but you knew that :)...


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.


Top
 Profile  
 
 Post subject: Re:apic timer
PostPosted: Fri Jul 15, 2005 2:20 am 
to me, that seems to be a very "inacurate science". I guess you'd really do have to get the RTC to control time. So what would the apic timer be usefull for? I'm guessing it can fire a lot more interrupts per second than anything else.


Top
  
 
 Post subject: Re:apic timer
PostPosted: Fri Jul 15, 2005 4:01 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

DruG5t0r3 wrote:
to me, that seems to be a very "inacurate science". I guess you'd really do have to get the RTC to control time. So what would the apic timer be usefull for? I'm guessing it can fire a lot more interrupts per second than anything else.


The local APIC timer is as accurate as the timer & code used to calibrate it, and can provide accurate timing for extremely small time values and very large values - a 100 MHz CPU bus gives delays as small as 10 nano-seconds and as large as (roughly) 5.5 seconds. Because it's built into the CPU there's no IO port delays or bus traffic overheads. It's the fastest and the most versatile timer the 80x86 has ever had.

The main use for the local APIC timer is schedulers - mostly because there's one for each CPU. For example, on my OS when the scheduler does a task switch it sets the local APIC timer to interrupt whenever the task should stop running (which depends on the task's priority), using "one shot" mode to minimize unnecessary interrupts. For this purpose accuracy isn't really that important (it doesn't worry me if a task gets to run for a millionth of a second longer or shorter).

For measuring real time I use the real time clock's periodic interrupt, and if the computer doesn't have a local APIC I use the PIT for the scheduler (which means the code to keep track of real time is done the same regardless of what the scheduler does).


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.


Top
 Profile  
 
 Post subject: Re:apic timer
PostPosted: Fri Jul 15, 2005 6:51 am 
k thanks, using it for a scheduler does make quite a lot of sense.


Top
  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: SemrushBot [Bot] and 20 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group