は、現在、私のIRQは、トリプル断層と0による除算エラーを与えることです。 Hereは記録されたviedoです。これは実際にあなたにこれを表示します。IRQハンドラトリプル障害
irq.C++:
#include "irq.h"
#define PIC_MASTER_CONTROL 0x20
#define PIC_MASTER_MASK 0x21
#define PIC_SLAVE_CONTROL 0xa0
#define PIC_SLAVE_MASK 0xa1
typedef void(*regs_func)(struct regs *r);
/*Get all irq's*/
extern "C" void irq0(void);
extern "C" void irq1(void);
extern "C" void irq2(void);
extern "C" void irq3(void);
extern "C" void irq4(void);
extern "C" void irq5(void);
extern "C" void irq6(void);
extern "C" void irq7(void);
extern "C" void irq8(void);
extern "C" void irq9(void);
extern "C" void irq10(void);
extern "C" void irq11(void);
extern "C" void irq12(void);
extern "C" void irq13(void);
extern "C" void irq14(void);
extern "C" void irq15(void);
extern void panic(const char* exception);
regs_func irq_routines[16] = {
0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0
};
static PORT::Port8Bits p8b_irq;
static SerialPort sp_irq;
//Basically a declaration of IDT_ENTRY in
//idt.c++
struct idt_entry {
uint16_t base_lo;
uint16_t sel; // Kernel segment goes here.
uint8_t always0;
uint8_t flags; // Set using the table.
uint16_t base_hi;
}__attribute__((packed));
//Get the Exact IDT array from idt.c++
extern struct idt_entry idt[256];
static inline void idt_set_gate(uint8_t num, void(*handler)(void), uint16_t sel,
uint8_t flags)
{
idt[num].base_lo = (uintptr_t)handler >> 0 & 0xFFFF;
idt[num].base_hi = (uintptr_t)handler >> 16 & 0xffff;
idt[num].always0 = 0;
idt[num].sel = sel;
idt[num].flags = flags;
}
IRQ::IRQ(){};
IRQ::~IRQ(){};
/* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
* is a problem in protected mode, because IDT entry 8 is a
* Double Fault! Without remapping, every time IRQ0 fires,
* you get a Double Fault Exception, which is NOT actually
* what's happening. We send commands to the Programmable
* Interrupt Controller (PICs - also called the 8259's) in
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
* 47 */
void IRQ::irq_remap()
{
// ICW1 - begin initialization
p8b_irq.out(0x11,PIC_MASTER_CONTROL);
p8b_irq.out(0x11,PIC_SLAVE_CONTROL);
// Remap interrupts beyond 0x20 because the first 32 are cpu exceptions
p8b_irq.out(0x21,PIC_MASTER_MASK);
p8b_irq.out(0x28,PIC_SLAVE_MASK);
// ICW3 - setup cascading
p8b_irq.out(0x00,PIC_MASTER_MASK);
p8b_irq.out(0x00,PIC_SLAVE_MASK);
// ICW4 - environment info
p8b_irq.out(0x01,PIC_MASTER_MASK);
p8b_irq.out(0x01,PIC_SLAVE_MASK);
// mask interrupts
p8b_irq.out(0xff,PIC_MASTER_MASK);
p8b_irq.out(0xff,PIC_SLAVE_MASK);
}
void install_handler_irq(int irq, regs_func handler)
{
printf(" \n Installer IRQ %d \n ", irq);
irq_routines[irq] = handler;
irq0();
}
void uninstall_handler_irq(int irq)
{
irq_routines[irq] = 0;
}
/* First remap the interrupt controllers, and then we install
* the appropriate ISRs to the correct entries in the IDT. This
* is just like installing the exception handlers */
void IRQ::install_irqs()
{
this->irq_remap();
idt_set_gate(32, irq0, 0x08, 0x8E);
idt_set_gate(33, irq1, 0x08, 0x8E);
idt_set_gate(34, irq2, 0x08, 0x8E);
idt_set_gate(35, irq3, 0x08, 0x8E);
idt_set_gate(36, irq4, 0x08, 0x8E);
idt_set_gate(37, irq5, 0x08, 0x8E);
idt_set_gate(38, irq6, 0x08, 0x8E);
idt_set_gate(39, irq7, 0x08, 0x8E);
idt_set_gate(40, irq8, 0x08, 0x8E);
idt_set_gate(41, irq9, 0x08, 0x8E);
idt_set_gate(42, irq10, 0x08, 0x8E);
idt_set_gate(43, irq11, 0x08, 0x8E);
idt_set_gate(44, irq12, 0x08, 0x8E);
idt_set_gate(45, irq13, 0x08, 0x8E);
idt_set_gate(46, irq14, 0x08, 0x8E);
idt_set_gate(47, irq15, 0x08, 0x8E);
}
/* Each of the IRQ ISRs point to this function, rather than
* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
* to be told when you are done servicing them, so you need
* to send them an "End of Interrupt" command (0x20). There
* are two 8259 chips: The first exists at 0x20, the second
* exists at 0xA0. If the second controller (an IRQ from 8 to
* 15) gets an interrupt, you need to acknowledge the
* interrupt at BOTH controllers, otherwise, you only send
* an EOI command to the first controller. If you don't send
* an EOI, you won't raise any more IRQs */
extern "C" void irq_handler(struct regs *r)
{
printf("IRQ Being Handled");
}
irq.S:
.section .text
.extern irq_handler
.extern test_func
.macro irq number
.global irq\number
irq\number:
cli
pushl $0
pushl $\number
jmp common_handler_irq
.endm
common_handler_irq:
# save registers
pusha
# call C++ Handler
call irq_handler
# restore registers
popa
iret
#TODO FOR LOOP
irq 0
irq 1
irq 2
irq 3
irq 4
irq 5
irq 6
irq 7
irq 8
irq 9
irq 10
irq 11
irq 12
irq 13
irq 14
irq 15
私はそのIRQ0を(削除する場合++ irq.cにviedoに示すような)install_irq機能で呼び出し、トリプル断層運動オフになります...しかし、私は私のタイマードライバを正しく処理する方法を知っていないことを削除する場合...
timer.C++:
#include "timer.h"
/* This will keep track of how many ticks that the system
* has been running for */
typedef void(*regs_func)(struct regs *r);
static int32_t timer_ticks = 0;
extern void install_handler_irq(int irq, regs_func handler);
/* Handles the timer. In this case, it's very simple: We
* increment the 'Timer::timer_ticks' variable every time the
* timer fires. By default, the timer fires 18.222 times
* per second. Why 18.222Hz? Some engineer at IBM must've
* been smoking something funky */
void timer_handler_driver(struct regs *r)
{
/* Increment our 'tick count' */
timer_ticks++;
/* Every 18 clocks (approximately 1 second), we will
* display a message on the screen */
if (timer_ticks % 18 == 0)
{
printf("One second has passed\n");
}
}
Timer::Timer()
{
}
/* This will continuously loop until the given time has
* been reached */
void Timer::timer_wait(int ticks)
{
unsigned long eticks;
eticks = timer_ticks + ticks;
while((unsigned)timer_ticks < eticks);
}
void Timer::install_timer()
{
install_handler_irq(0, timer_handler_driver);
}
/* Sets up the system clock by installing the timer handler
* into IRQ0 */
Timer::~Timer()
{
}
あなたは私の全体のコードを表示したい場合。 githubで私のコードを更新します:https://github.com/amanuel2/OS_Mirror。ヘルプは非常に高く評価される、私は今この問題にしばらくの間立ち往生している。読んでくれてありがとう。
カルビン、私はあなたのanwserに関する多くの質問があります。私はチャットルームを洪水したくないので、ここに来るかもしれません:https://kobra.io/#/e/-KOjaiMeGtgwYkEsAvuu。それについて議論する?ありがとう – amanuel2
@DsafdsあなたのISRには、あなたのCコードの関数として宣言しないで良いでしょうCから呼び出すことはできませんので。また、チャットするためにここに新しい部屋を作成して、他の部屋を「洪水」しないようにすることができます。 –