Files
x86-bare-metal-examples/pit.S
Ciro Santilli 9a33f2a5c7 pit sleep works
2015-11-11 09:23:01 +01:00

80 lines
2.0 KiB
ArmAsm

/*
# PIT
Programmable interrupt timer.
Expected output: "a\n" is printed infinitely many times.
Generates periodic interrupts (or sound!) with a given frequency to IRQ0,
which on real mode maps to interrupt 8 by default.
Major application: interrupt the running process
to allow the OS to schedule processes.
Read this *now*: http://wiki.osdev.org/PIT
Has 3 channels that can generate 3 independent signals
- channel 0 at port 0x40: generates interrupts
- channel 1 at port 0x41: not to be used for some reason
- channel 2 at port 0x42: linked to the speaker to generate sounds
Port 0x43 is used to control signal properties except frequency
(which goes in the channel ports) for the 3 channels.
See osdev article for details.
## Frequency
## 1193181
We don't control the frequency of the PIT directly,
which is fixed at 1193181.
Instead, we control a frequency divisor.
This is an well known type of discrete electronic circuit:
https://en.wikipedia.org/wiki/Frequency_divider
1193181 has 2 occurrences on Linux 4.2.
The frequency comes from historical reasons to reuse television hardware.
## Maskable interrupts
## sti
http://wiki.osdev.org/Non_Maskable_Interrupt
Interrupts generated by the CPU from 0 - 31 are not maskable: they generate interrupts even with `cli`.
Those from the PIC are maskable however.
QEMU generates many maskable interrupts by default. TODO: where do they come from? What are they excatly?
If we don't set a handler, we usually triple-fault and the machine restarts, thus going into a restart loop.
## Bibliography
- https://en.wikipedia.org/wiki/Intel_8253 That is the circuit ID for the PIT.
- http://kernelx.weebly.com/programmable-interval-timer.html
TODO learn to turn off the PIT after some iterations
*/
#include "common.h"
BEGIN
IVT_PIT_SETUP
PIT_GENERATE_FREQUENCY
PIT_SET_MIN_FREQ
/* If we comment out sti, nothing happens, because the PIT interrupts are maskable. */
sti
jmp .
handler:
cli
PUTC $'a
PUTC $'\n
/* EOI: it will not fire again unless we reset it. */
PIC_EOI
sti
iret