简述可编程控制器的定义:如何使用可编程中断控制器PIC和可编程间隔定时器PIT在内核上调度进程

关于简述可编程控制器的定义的问题,在what is programmable interval timer中经常遇到, 在我的“wannabe-kernel”中,我已经成功地在保护模式下通过 IDT 启用了软件中断处理。现在我正在转向硬件中断,以便能够为进程分配时间片。问题是我的内核没有收到任何 PIT 中断。

在我的“wannabe-kernel”中,我已经成功地在保护模式下通过 IDT 启用了软件中断处理。现在我正在转向硬件中断,以便能够为进程分配时间片。问题是我的内核没有收到任何 PIT 中断。

inline void outb(uint8_t port,unsigned char value)
    {
       __asm__ __volatile__ ("outb %%ax,%%dx": :"d" (port), "a" (value));
    }
    static inline uint8_t inb(uint16_t port)
    {
        uint8_t ret;
        __asm__ __volatile__ ( "inb %1, %0" : "=a"(ret) : "d"(port) );
        return ret;
    }
    #define PIC1    0x20
    #define PIC2  0xA0   
    #define PIC1_COMMAND    PIC1
    #define PIC1_DATA       (PIC1+1)
    #define PIC2_COMMAND    PIC2
    #define PIC2_DATA       (PIC2+1)
    #define ICW1_ICW4       0x01        
    #define ICW1_SINGLE     0x02        
    #define ICW1_INTERVAL4  0x04        
    #define ICW1_LEVEL      0x08        
    #define ICW1_INIT       0x10        
    #define ICW4_8086       0x01    
    #define ICW4_AUTO       0x02        
    #define ICW4_BUF_SLE  0x08
    #define ICW4_BUF_MASTER 0x0C    
    #define ICW4_SFNM       0x10
    void init_pic()
    {
        unsigned char a1, a2;
        unsigned offset_master = 0x20;
        unsigned offset_slave = 0x28;
        a1 = inb(PIC1_DATA);                        
        a2 = inb(PIC2_DATA);
        outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);  
        outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
        outb(PIC1_DATA, offset_master);                 
        outb(PIC2_DATA, offset_slave);                 
        outb(PIC1_DATA, 4);                      
        outb(PIC2_DATA, 2);                       
        outb(PIC1_DATA, ICW4_8086);
        outb(PIC2_DATA, ICW4_8086);
        outb(PIC1_DATA, a1); 
        outb(PIC2_DATA, a2);
    }
    #define PIT_COMMAND 0x43
    #define PIT_DATA1   0x40
    #define PIT_DATA2   0x41
    #define PIT_DATA3   0x42
    void init_pit()
    {
       uint32_t divisor = 1193180 / 50;
       outb(PIT_COMMAND, 0x36);
       uint8_t l = (uint8_t)(divisor & 0xFF);
       uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );
       outb(PIT_DATA1, l);
       outb(PIT_DATA1, h);  
    }

和计时器处理程序

    unsigned tick = 0;
    void timerHandler()
    {
       tick++;
       char* ascii_code;
       itoa(ascii_code, 'd', tick);
       terminal_writestring("PIT Tick: ", &terminal);
       terminal_writestring(ascii_code, &terminal);
       terminal_writestring("\n", &terminal);
    }

bochs 没有提供有关 isse 原因的太多详细信息:

00122970752e[CPU0  ] interrupt(): gate descriptor is not valid sys seg       (vector=0x20)
00122970752e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00122970752e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)

我已经注册到 IDT 定时器处理程序相同的方式(只有条目号不同)作为软件中断处理程序。
编辑:IDT 设置代码要求:

    struct __InteruptDescriptorTableEntry
    {
       uint16_t offset_low;
       uint16_t selector; 
       uint8_t zero;      
       uint8_t type_attr; 
       uint16_t offset_up; 
    } __attribute__((packed));
    typedef struct __InteruptDescriptorTableEntry IDTEntry;
    struct _ITD_PTR
    {
        uint16_t idtSize;
        uint32_t idtBaseAddr;
    } __attribute__((packed));
    typedef struct _ITD_PTR _IDT_PTR;
    void zeroIDT()
    {   
        unsigned i;
        for(i=0;i<NUM_IDT_ENTRIES-1;++i)
        {
            IDTEntry nullIDTEntry = fillIDTEntry(0,0,0);
            registerInterupt(nullIDTEntry, i);
        }
    }
    void registerInterupt(const IDTEntry entry, const unsigned intNo)
    {
        if(intNo < NUM_IDT_ENTRIES)
            InteruptDescriptorTable[intNo] = entry;
    }
    #define LOW_FUN_ADDR(fun) ( (uint32_t)fun & 0xFFFF )
    #define UP_FUN_ADDR(fun) ( (uint32_t)fun >> 16) & 0xFFFF
    IDTEntry fillIDTEntry(uint32_t intHandler,
                          uint16_t selector,   
                          uint8_t type_attr)
    {   IDTEntry newEntry;
        newEntry.offset_low = LOW_FUN_ADDR(intHandler); 
        newEntry.selector = selector; 
        newEntry.zero = 0;     
        newEntry.type_attr = type_attr;
        newEntry.offset_up = UP_FUN_ADDR(intHandler);
        return newEntry;
    }
    extern void _lidt(_IDT_PTR* idtPtr);
    void timerHandler_TEST();
    void loadIDT()
    {
        zeroIDT();
        _IDT_PTR idtPtr;
        idtPtr.idtSize = sizeof(struct __InteruptDescriptorTableEntry)*256 - 1;
        idtPtr.idtBaseAddr = (uint32_t) &InteruptDescriptorTable;
        IDTEntry printOnScreenInt = fillIDTEntry((uint32_t)interupt_pritnOnScreen, 0x18, 0xee);
        registerInterupt(printOnScreenInt, 50);
        IDTEntry timerIntEntry = fillIDTEntry((uint32_t)timerHandler_TEST, 0x18, 0xee);
        registerInterupt(printOnScreenInt, 13);
        _lidt(&idtPtr);
    }

程序集来源:

.global _lidt
_lidt:
    push %ebp
    mov %esp,%ebp
    mov 8(%esp), %eax
    lidt (%eax)
leave
ret

EDIT2:我已经改变了坑的面具:

a1 = 0x7F; //master                        
a2 = 0xFF; //slave

只接收 PIT int,但不传送 IRQ(无三重故障)。
EDIT3:info gdtinfo IDT

IDT[0x20]=32-Bit Interrupt Gate target=0x0018:0x001009c0, DPL=3
IDT[0x32]=32-Bit Interrupt Gate target=0x0018:0x001009c0, DPL=3
GDT:
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x05]=32-Bit TSS (Busy) at 0x00101000, length 0x00068

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(182)
Ps教程抠图:'docker ps-all'和'docker ps-a'有什么区别
上一篇
Engineering base:逆向工程 DLL(swtor reverse engineering)
下一篇

相关推荐

  • cvt和自动挡哪个好提升驾驶体验的最佳选择

    CVT(可变转换器)是一种由传动带及传动轮组成的无级变速器,它可以在没有传动档位的情况下,根据驾驶者的驾驶习惯,自动调整传动轮之间的转速比,从而实现无级变速。自动挡是指车辆自动变速箱,它使用液力传动来实现变速,可以自动适应车辆的行驶状态,减少司机的疲劳,提高行车的舒适性。…

    2023-06-08 07:42:19
    0 97 49
  • cv一叶扁舟和清影轩阳:漫游在一叶扁舟和清影轩阳之间

    cv一叶扁舟是一款开源的计算机视觉库,用于图像处理、计算机视觉等。它提供了丰富的API,可以帮助开发者快速实现各种图像处理任务,如图像分割、目标检测、图像识别等。清影轩阳是一款开源的计算机视觉框架,用于图像处理、目标检测、分类等。它提供了丰富的API,可以帮助开发者快速实现各种图像处理任务,如图像分割、目标检测、图像识别等。…

    2023-08-05 07:06:20
    0 94 21
  • css设置滚动条宽度设置:This is a title

    CSS设置滚动条宽度的方法:使用CSS3的。-webkit-属性:…

    2023-06-06 10:53:01
    0 91 18
  • xl和xe汽车cvt:探索XL和XE汽车的CVT技术优势

    XL和XE汽车CVT是一种变速器,它使用液力变矩器代替传统的机械变速器,以达到更高的效率。它的工作原理是,当发动机输出功率时,液力变矩器就会将这些功率转换为液压能量,然后将能量传递到变速器的输出轴上,从而实现变速。…

    2023-04-09 00:41:04
    0 65 99
  • cordon bleu是什么意思:法式炸鸡卷——Cordon Bleu的经典之作

    Cordon Bleu是一种烹饪技术,其中肉片被置于奶酪和火腿之间,然后用面包屑裹上,最后煎炸或烤熟。这种技术通常用于制作鸡肉,但也可以用于制作其他类型的肉类,如牛肉或猪肉。…

    2024-01-27 15:13:30
    0 53 54
  • countif 非空:非空单元格的计数

    Countif 非空是指计算某个单元格不为空的数量。代码如下:…

    2023-04-22 15:54:15
    0 98 94
  • java double保留一位小数:How to Round a Double to One Decimal Place in

    示例示例使用类可以轻松实现java double保留一位小数的功能,具体代码如下:// 创建对象…

    2023-05-14 07:40:03
    0 35 79
  • linux如何写c语言一个完整的指南

    示例示例在Linux系统中,可以使用C语言编写源代码文件,然后使用GCC编译器来编译源代码文件,生成可执行文件。下面是一个简单的C语言代码示例:…

    2023-05-16 02:02:45
    0 49 57

发表评论

登录 后才能评论

评论列表(75条)