如何为8259控制器编写C程序

时间:2014-03-20 10:46:29

标签: c

我正在研究中断。我必须了解如何使用8259 PIC。任何人都可以指导我如何用C编写程序。 (我已经在8051上工作了)我想它可以用作8051。

1 个答案:

答案 0 :(得分:3)

这只是本节其余部分共同的一组定义。对于outb(),inb()和io_wait()函数,see this page.

#define PIC1        0x20        /* IO base address for master PIC */
#define PIC2        0xA0        /* IO base address for slave PIC */
#define PIC1_COMMAND    PIC1
#define PIC1_DATA   (PIC1+1)
#define PIC2_COMMAND    PIC2
#define PIC2_DATA   (PIC2+1)

向PIC芯片发出的最常见命令可能是中断结束(EOI)命令(代码0x20)。这是在基于IRQ的中断例程结束时发给PIC芯片的。如果IRQ来自主PIC,则仅向主PIC发出此命令就足够了;但是,如果IRQ来自Slave PIC,则必须向两个PIC芯片发出命令。

#define PIC_EOI     0x20        /* End-of-interrupt command code */

void PIC_sendEOI(unsigned char irq)
{
    if(irq >= 8)
        outb(PIC2_COMMAND,PIC_EOI);

    outb(PIC1_COMMAND,PIC_EOI);
}

当你进入保护模式时(或者甚至在手之前,如果你没有使用GRUB),你需要给出两个PIC的第一个命令是初始化命令(代码0x11)。该命令使PIC等待数据端口上3个额外的“初始化字”。这些字节给出了PIC:

  1. 其向量偏移量。 (ICW2)
  2. 告诉它如何连接到主/从。 (ICW3)
  3. 提供有关环境的其他信息。 (ICW4)
  4. #define ICW1_ICW4 0x01        /* ICW4 (not) needed */
    #define ICW1_SINGLE   0x02        /* Single (cascade) mode */
    #define ICW1_INTERVAL4    0x04        /* Call address interval 4 (8) */
    #define ICW1_LEVEL    0x08        /* Level triggered (edge) mode */
    #define ICW1_INIT 0x10        /* Initialization - required! */
    
    #define ICW4_8086 0x01        /* 8086/88 (MCS-80/85) mode */
    #define ICW4_AUTO 0x02        /* Auto (normal) EOI */
    #define ICW4_BUF_SLAVE    0x08        /* Buffered mode/slave */
    #define ICW4_BUF_MASTER   0x0C        /* Buffered mode/master */
    #define ICW4_SFNM 0x10        /* Special fully nested (not) */
    
    void PIC_remap(int offset1, int offset2)
    {
        unsigned char a1, a2;
    
        a1 = inb(PIC1_DATA);                        // save masks
        a2 = inb(PIC2_DATA);
    
        outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);  // starts the initialization sequence (in cascade mode)
        io_wait();
        outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
        io_wait();
        outb(PIC1_DATA, offset1);                 // ICW2: Master PIC vector offset
        io_wait();
        outb(PIC2_DATA, offset2);                 // ICW2: Slave PIC vector offset
        io_wait();
        outb(PIC1_DATA, 4);                       // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
        io_wait();
        outb(PIC2_DATA, 2);                       // ICW3: tell Slave PIC its cascade identity (0000 0010)
        io_wait();
    
        outb(PIC1_DATA, ICW4_8086);
        io_wait();
        outb(PIC2_DATA, ICW4_8086);
        io_wait();
    
        outb(PIC1_DATA, a1);   // restore saved masks.
        outb(PIC2_DATA, a2);
    }
    

    用于屏蔽

    void IRQ_set_mask(unsigned char IRQline) {
        uint16_t port;
        uint8_t value;
    
        if(IRQline < 8) {
            port = PIC1_DATA;
        } else {
            port = PIC2_DATA;
            IRQline -= 8;
        }
        value = inb(port) | (1 << IRQline);
        outb(port, value);        
    }
    
    void IRQ_clear_mask(unsigned char IRQline) {
        uint16_t port;
        uint8_t value;
    
        if(IRQline < 8) {
            port = PIC1_DATA;
        } else {
            port = PIC2_DATA;
            IRQline -= 8;
        }
        value = inb(port) & ~(1 << IRQline);
        outb(port, value);        
    }