中断控制芯片的初始化
参考:https://blog.csdn.net/longintchar/article/details/79439466
中断控制芯片8259A由主从两个芯片级联而成
从片的输出接在主片的IRQ2上,所以一共可以接受15个设备的中断信号,中断控制芯片的作用就是管理外接设备的中断
首先要对芯片进行初始化,初始化该芯片就是初始化一组寄存器ICW寄存器
当地址线的A0=0时主片的端口的0x20,从片的端口是0xA0
ICW1
首先设置ICW1,ICW1寄存器一共有8位,作用分别为
这里我们给它设置为0x11即0001 0001,就是D4和D0为1
在idt.c中的init_idt()
函数最前面加上
ICW芯片组的初始化是有顺序的,必须从ICW1到ICW4
1 | //初始化主从芯片的ICW1 |
outb就是之前在common.c里实现的cpu对cpu外设备的写函数
ICW2
然后是初始化ICW2,它的高五位表示送出的中断号的高五位,低三位由芯片根据当前的IR0-IR7自动填入对应的二进制串
通过前面的设计知道0-31号中断是cpu保留的,所以这里主片的IR0就从第32号中断开始,从片的IR0就是第40号中断。
如何设置ICW2呢,在ICW1设置之后,地址线A0会变成1,这时代表设置的就是ICW2,当A0为1时,主片的端口是0x21,从片的端口是0xA1
所以我们在上面的代码下面加上
1 | //初始化主片的ICW2,让主片的中断号从32-39 |
ICW3
此时地址线A0还是1
主片的ICW3的8位代表的是连接从片的情况,哪一位为1就代表哪一位的IRx连接了从片,这里是IR2连接从片所以值为0x04(0000 0100)
从片的ICW3高五位为0,低三位表示的是该从片连接的是主片的哪一个IR,所以这里设置成0x02代表该从片连接的是主片的IR2
加上如下代码
1 | //设置从片连接主片的IR2 |
ICW4
这里设置成0x01。表示 8259A 芯片被设置成普通全嵌套、非缓冲、非自动结束中断方式,并且用于 8086 及其兼容系统。
1 | //设置芯片以8086方式工作 |
设置完ICW之后芯片就可以工作了,在工作过程中可以设置OCW芯片组来控制工作状态,OCW的使用不需要按顺序了
OCW1
现在设置一下OCW1,OCW1的八位,哪一位为1代表屏蔽哪一级中断,现在我们都不屏蔽
1 | //开放所有中断 |
现在初始化就完成了。
IRQ的处理
IRQ的处理和ISR函数的处理类似,首先定义IRQ函数
在idt.h最后加上
1 | // IRQ 处理函数 |
然后去idt_s.s中添加相应的处理过程,这部分和isr很相似,唯一不同的是IRQ的宏有两个参数,因为IRQx的中断号不是x
1 | ; 构造中断请求的宏 |
然后就是去idt.c中构造这些IRQ的中断描述符和实现IRQ处理函数了
1 | init_idt() |
这里的重置信号其实是OCW2控制的
设置时钟中断
时钟中断是操作系统运行的脉搏,通过定时产生一个中断来让操作系统进行对进程进行调度之类的操作
时钟中断由Intel 8253 (8254)芯片产生,所以要先对它进行初始化
driver/timer.c
1 |
|
timer_callback
函数就产生中断是调用的中断处理函数,这里只是测试就写了打印
8253/8254芯片的工作模式3下是方波发生器方式,该方式下产生的方波的频率为输入时钟频率的N分之一,该芯片输入时钟是1193180HZ,N就是我们设置给它的参数,所以我们想它每10ms(100HZ)产生一次IRQ0的信号也就是每10ms产生一个方波,那么N取值就是1193180/100
对应的头文件include/timer.h
1 |
|
修改init/entry.c测试一下
1 | #include "console.h" |