Linux Kernel series-8. Clock interruption in operating system development, Linux Kernel
External interruptions are complicated because the correspondence between hardware interruptions and Vector Numbers needs to be established. The external interrupt is divided into two types: unshielded interrupt (NMI) and shielded interrupt, which are received by the two CPU pins NMI and INTR respectively. As shown in:
The relationship between the interrupt and the CPU can be shielded through the 8259A Programmable Interrupt Controller. It can be considered as a proxy for all peripheral devices in the interrupt mechanism. When the BIOS initializes it, IRQ0 ~ IRQ7 is set to the corresponding vector number 08h ~ 0Fh. In protection mode, the vector number is 08h ~ 0Fh is occupied, so we have to reset the Master/Slave 8259A.
The 8259A setting is not complex. It is implemented by writing a specific ICW to the corresponding port. The ports corresponding to the master 8259A are 20 h and 21 h, and the ports corresponding to 8259A are A0h and A1h. There are 4 ICWs in total. The initialization process is as follows:
1. Write ICW1.
2. Write ICW2.
3. Write ICW3.
4. Write icw4to port 21 h (main chip) or A1h (slave chip.
The order of the four steps cannot be reversed.
The ICW format is as follows:
Init8259A: moval, interval, al; Master 8259, ICW1.callio _ delayout0A0h, al; from 8259, ICW1.callio _ delaymoval, 020 h; IRQ0 corresponds to the interrupt vector 0x20out021h, vertex _ delaymoval, 028 h; IRQ8 corresponds to the interrupt vector 0x28out0A1h, al; from 8259, ICW2.callio _ delaymoval, 004 h; IR2 corresponds to slave, al; Master 8259, ICW3.callio _ delaymoval, 002 h; corresponding to primary 8259 values, al; from 8259, ICW3.callio _ delaymoval, clerk, al; Primary 8259, ICW4.callio _ delayout0A1h, al; from 8259, ICW4.callio _ delaymoval, 11111110b; enable only the timer interrupt; moval, 111111b; shield the main 8259 from all interrupts out021h, al; main 8259, OCW1.callio _ delaymoval, 111111b; shield all interrupts from 8259 out0A1h, al; from 8259, OCW1.callio _ delayret
We use operations on ports 21h and A1h to block all external interruptions and write data into OCW. We use them in the following two cases:
1. Block or open external interruptions.
2. Send EOI to 8259A to notify it of the end of Interrupt Processing.
To block or enable external interruptions, you only need to write OCW1 to 8259A. The OCW1 format is as follows:
If you want to block an interrupt, set the corresponding one to 1. EOI is to send an EOI to 8259A when the processing of each interruption ends, in order to continue receiving the interruption. EOI is sent by writing OCW2 to the Port 20 h or A0h. Shows the OCW2 format.
The following code sends EOI to 8259A:
Mov al, 20 hout 20 h or A0h, al
In this case, the clock interruption (IRQ0) is enabled. It can be blocked by two factors. Only when the if bit is 1 and the IMR bit is 0.
IF we want to enable clock interruption, on the one hand, we should not only design an interrupt processing program, but also set IMR and IF bit. Setting IMR can be done by writing OCW2, and setting IF can be done by executing the command sti.
First write a clock interrupt handler
_ ClockHandler: ClockHandlerequ_ClockHandler-$ incbyte [gs :( (80*0 + 70) * 2)]; screen 0th rows, 70th columns. Moval, 20hout20h, al; sends EOIiretd
Modify the code for initializing 8259A, and the clock interruption will not be blocked.
Moval, 11111110b; only enable timer interrupt; moval, 11111111b; shield the main 8259 from all interrupts out021h, al; main 8259, OCW1.callio _ delaymoval, 11111111b; shield all interrupts from 8259 out0A1h, al; from 8259, OCW1.callio _ delay
Modify IDT:
%rep 32GateSelectorCode32, SpuriousHandler, 0, DA_386IGate%endrep.020h:GateSelectorCode32, ClockHandler, 0, DA_386IGate%rep 95GateSelectorCode32, SpuriousHandler, 0, DA_386IGate%endrep.080h:GateSelectorCode32, UserIntHandler, 0, DA_386IGate
Running result:
【Source code]