- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
目前我的 IRQ 是三重故障并给出除以 0 的错误。 Here是我录制的视频,它将向您展示这一点。
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");
}
中断请求:
.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
如 viedo 所示在 irq.c++ 中,如果我删除在 install_irq 函数中调用的 irq0(),三重故障将关闭...但是如果我删除它,我不知道如何正确处理我的定时器驱动程序...
定时器.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 .帮助将不胜感激,我已经在这个问题上停留了一段时间了。感谢阅读。
最佳答案
irq0()
是一个中断服务程序,以iret
结束。您不能对该例程执行 C 调用。如果你真的想触发中断,使用int
指令。
但是,您实际上并不需要手动触发定时器 IRQ,它应该在您配置定时器/APIC 后触发,并在您sti
时接收中断。
作为旁注,对于“通用 IRQ 处理程序”方法,它被认为是不好的做法(浪费时钟周期和污染缓存),然后只进行手动切换分支,不同的 IRQ 可能需要不同的处理(例如。奴隶的意向书)。只需将处理程序直接安装到 IDT。
调查总结:
经调查,是重新映射代码导致了故障,掩码设置为 0xff,这样 PIT 就被忽略了。解决此问题(将 0 设置为屏蔽)会导致三重错误,这表明定时器随后被触发,但 IDT/IRQ 链中的其他地方会出现问题。
关于c++ - IRQ 处理程序三重故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38852419/
我正在使用线程 irq 实现一个中断处理模块。我面临这个错误: 1983.150961] Shut down eMMC app module init. [ 1983.151115] genirq:
我有一个 GPIO 外围设备,在设备树中定义为: gpio0: gpio@2300000 { compatible = "fsl,qoriq-gpio"; reg = ; in
我已经构建了一个静态库(*.a 用于 gcc,*.lib 用于 keil)。它的源文件之一,编译成库,包含 RADIO_IRQHandler 的定义。下面是这个名为“ral_irq_handlers.
从: http://software.intel.com/en-us/articles/introduction-to-pc-architecture/ 异常编号 10h 对应于“浮点错误”,但软件中
我正在学习 Linux 内核中的中断处理,并尝试使用下面的代码片段在 IRQ2 上注册一个虚拟 irq 处理程序。但它似乎没有被注册,因为我在内核中看到了一个负返回值和一条消息,如下所示,这是由试图执
我在制作我的第一个驱动程序 (PIT) 时遇到了问题。我之前录制的视频中清楚地解释了这个问题:https://www.youtube.com/watch?v=hjvTtVbaics&feature=y
目前我的 IRQ 是三重故障并给出除以 0 的错误。 Here是我录制的视频,它将向您展示这一点。 irq.c++: #include "irq.h" #define PIC_MASTER_CONTR
我是 Linux 内核模块开发的新手,正在尝试编写一个简单的内核模块,稍后可以将其扩展为键盘驱动程序。 我尝试了以下两种方法: 基于中断的方法 我按照给定的指南开始编写代码 here .但唯一的问题是
我有一些关于 PCI 和 IRQS 的问题。 IRQ 是如何分配给连接到 PCI 总线的设备的,它是由 BIOS 在启动时分配的,还是总线选择它或总线 Controller 自己自动选择它,谁负责选择
如果我的 PC 有两个内核——CPU0 和 CPU1,则 CPU0 的 IRQ 被禁用 (local_irq_disabled())。如何使用CPU1上的进程开启CPU0的IRQ? 最佳答案 不要。
如何在 32 位保护模式(显然是 x86)下查看 PIT IRQ 处理程序的返回值?我想我可以这样做,但我不完全确定。 pop eax ; pop last thing from stack mov
如何在 32 位保护模式(显然是 x86)下查看 PIT IRQ 处理程序的返回值?我想我可以这样做,但我不完全确定。 pop eax ; pop last thing from stack mov
我正在开发一个使用 ARM Cortex-M0 处理器的项目。在这个项目中,我需要提供计时器支持(CMSDK (SSE-200)计时器)。 因此,在 vector 表中,在 TIMER0_IRQn 表
我正在浏览下面的线程,它说内核头不想将 irq 暴露给模块。 Accessing IRQ description array within a module and displaying action
我是 Linux 内核编程的新手,很长一段时间以来我都在尝试编写模块,它应该执行以下操作:用我自己的替换默认的 irq 处理程序,然后恢复默认的处理程序,使用 IDT (尝试保存 idt 用我自己的替
当一个 IRQ 线在多个已注册的中断服务例程之间共享时,什么决定了中断线产生时 ISR 的执行顺序? 最佳答案 无论如何,顺序是不可预测的,因为正如你所说,中断线是共享的。因此,系统中有(或可能有)其
我正在浏览 arch/arm/kernel/perf_event.c 中的部分 Linux 内核源代码,并试图了解如何进行 request_irq 设置这里: static int armpmu_re
我正在开发一个玩具 unix 克隆,我正在尝试正确连接我的中断。我遇到了一个问题,我的键盘 IRQ (IRQ 1) 即使在我正确确认它之后也只触发一次等等。我也启用了 PIT 中断,以仔细检查我的 A
我目前正在学习 Derek Molloy 在他的书“Exploring Raspberry Pi - Interfacing to The Real World with Embedded Linux
我正在用 C 编写一个内核模块,它正在努力访问 IRQ 描述数组元素并显示这些元素的所有操作名称。 一开始,我认为这个irq_desc 数组就像一个宏,但编译后我明白了它不是。然后我使用了 for_e
我是一名优秀的程序员,十分优秀!