[SOLVED] Only receiving one RTC interrupt ...
[SOLVED] Only receiving one RTC interrupt ...
I'm working on an RTC driver, and am only receiving one interrupt from it immediately after setting the IF flag. I've set the rate in CMOS RTC status register A and enabled RTC periodic interrupts in CMOS RTC status register B. I've unmasked IRQ2 and IRQ8, and have a valid IDT entry for IRQ8. I receive IRQ0 and IRQ1 just fine. I am reading the CMOS RTC status register C before enabling interrupts, and then again in my IRQ8 handler (before PIC EOI).
Here is the relevant code:
RTC configuration: https://github.com/Izzette/izix/blob/rt ... cmos/rtc.c
CMOS read/write functions: https://github.com/Izzette/izix/blob/rt ... mos/cmos.c
IRQ8 hook (and other stuff): https://github.com/Izzette/izix/blob/rt ... ock_tick.c
Thanks for your help! I'll add any code or debugging info you'd like to see.
Here is the relevant code:
RTC configuration: https://github.com/Izzette/izix/blob/rt ... cmos/rtc.c
CMOS read/write functions: https://github.com/Izzette/izix/blob/rt ... mos/cmos.c
IRQ8 hook (and other stuff): https://github.com/Izzette/izix/blob/rt ... ock_tick.c
Thanks for your help! I'll add any code or debugging info you'd like to see.
Last edited by Izzette on Mon May 29, 2017 6:05 pm, edited 1 time in total.
-
- Member
- Posts: 799
- Joined: Fri Aug 26, 2016 1:41 pm
- Libera.chat IRC: mpetch
Re: Only receiving one RTC interrupt ...
Do you send an End of Interrupt (EOI) to the appropriate PIC before doing the IRET from your timer handler?
Last edited by MichaelPetch on Sat May 27, 2017 9:22 pm, edited 1 time in total.
Re: Only receiving one RTC interrupt ...
Yeah, I send an EOI to the master in the IRQ0,1,3-7 handlers, and one to the slave in IRQ8-15 handlers, after re-enabling interrupts (I'm using interrupt gates not trap gates), but before IRET.
Re: Only receiving one RTC interrupt ...
Hi,
Specifically, in pic_8259.c, this:
Probably needs to be more like this:
Cheers,
Brendan
I think you're right.MichaelPetch wrote:Do you send an End of Interrupt (EOI) to the master PIC (Since you are dealing with IRQ0) before doing the IRET from your timer handler?
Specifically, in pic_8259.c, this:
Code: Select all
void pic_8259_send_eoi (irq_t irq) {
outb (PIC_EOI, pic_8259_get_pic_cmd_port (irq));
}
Code: Select all
void pic_8259_send_eoi (irq_t irq) {
if (pic_8259_is_slave_irq (irq)) {
outb (PIC_EOI, PIC_SLAVE_CMD);
}
outb (PIC_EOI, PIC_MASTER_CMD);
}
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Only receiving one RTC interrupt ...
Hi,
If you don't send EOI to master, then the PIC chip's "IRQ priorities" prevent lower priority IRQs (IRQs 8, 9, 10, 11, 12, 13, 14, 15, 3, 4, 5, 6 and 7) from being sent to the CPU, but higher priority IRQs (IRQs 0 and 1) do keep working.
Note: While browsing your code I also noticed that you don't handle spurious IRQs properly. If IRQ7 occurs you should ask the master PIC if it's a spurious IRQ and ignore it (without sending EOI) if it is; and if IRQ15 occurs you should ask the slave PIC if it's a spurious IRQ and if it is only send EOI to the master PIC but not the slave PIC.
Cheers,
Brendan
If the slave sees an IRQ, then it's a little bit like the slave triggers "IRQ2" on the master (except the master doesn't send the "interrupt vector" to the CPU and lets the slave send it); which means that you need to send an EOI to the slave (to clear its IRQ8) and then send an EOI to the master (to clear its IRQ2).Izzette wrote:Yeah, I send an EOI to the master in the IRQ0,1,3-7 handlers, and one to the slave in IRQ8-15 handlers, after re-enabling interrupts (I'm using interrupt gates not trap gates), but before IRET.
If you don't send EOI to master, then the PIC chip's "IRQ priorities" prevent lower priority IRQs (IRQs 8, 9, 10, 11, 12, 13, 14, 15, 3, 4, 5, 6 and 7) from being sent to the CPU, but higher priority IRQs (IRQs 0 and 1) do keep working.
Note: While browsing your code I also noticed that you don't handle spurious IRQs properly. If IRQ7 occurs you should ask the master PIC if it's a spurious IRQ and ignore it (without sending EOI) if it is; and if IRQ15 occurs you should ask the slave PIC if it's a spurious IRQ and if it is only send EOI to the master PIC but not the slave PIC.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Only receiving one RTC interrupt ...
It's strange, I'm still receiving IRQ0 and IRQ1, I'd think if I needed to send EOI to the master PIC I wouldn't receive those ... But, I'll make that change *fingers crossed*.
Yeah, I know I don't handle spurious IRQs, but I'm just using QEMU for now and they don't happen on virtual hardware (right?)
Yeah, I know I don't handle spurious IRQs, but I'm just using QEMU for now and they don't happen on virtual hardware (right?)
Re: Only receiving one RTC interrupt ...
That was it, I needed to send EOI to master and slave for IRQs from the slave PIC. I get my RTC interrupts now. Thanks so much for your time!
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Only receiving one RTC interrupt ...
It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Re: Only receiving one RTC interrupt ...
A spurious interrupt is caused by electrical noise from the activity (usually high activity) of other interrupts and just happens (due to technical reasons)onlyonemac wrote:It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.
to end up on IRQ 7 and has little to do with printers.
Re: Only receiving one RTC interrupt ...
Hi,
Fortunately it's easy to support spurious IRQs properly, for example maybe something like:
Cheers,
Brendan
The problem is that if an OS doesn't support spurious IRQs properly nasty things can happen (depending on how the OS is written). Some OSs could simply crash because IRQ7 or IRQ15 was masked in the PIC and there's no IRQ handler or IDT entry for IRQ7 or IRQ15. Some (most?) OSs would send an EOI for the spurious IRQ where the PIC thinks the EOI is for a completely unrelated IRQ, which can mean that the unrelated IRQ is "ended" before it's ever sent to the CPU (which can cause an unrelated device to get stuck in a "driver waiting for IRQ that never arrives" state where the device no longer works); or can cause an unrelated IRQ to be sent a second time causing further problems.onlyonemac wrote:It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.
Fortunately it's easy to support spurious IRQs properly, for example maybe something like:
Code: Select all
IRQ7:
push eax
mov al,0x0B ;al = "read ISR" command
out 0x20,al ;Send "read ISR" command
in al,0x20 ;al = ISR for master PIC
test al,0x80 ;Is it a spurious IRQ7?
je .spuriousIRQ7 ; yes
pop eax
push dword 7 ;Put "IRQ number" on stack
jmp commonIRQhandler
.spuriousIRQ7:
inc dword [spuriousIRQ7counter]
pop eax
iret
IRQ15:
push eax
mov al,0x0B ;al = "read ISR" command
out 0xA0,al ;Send "read ISR" command
in al,0xA0 ;al = ISR for slave PIC
test al,0x80 ;Is it a spurious IRQ15?
je .spuriousIRQ15 ; yes
pop eax
push dword 15 ;Put "IRQ number" on stack
jmp commonIRQhandler
.spuriousIRQ15:
inc dword [spuriousIRQ15counter]
mov al,0x20
out 0x20,al ;Send EOI to master PIC (but not slave)
pop eax
iret
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Only receiving one RTC interrupt ...
Thanks, I'll make sure to handle spurious IRQs properly before I figure out why my bootloader is triple faulting on the one real computers I've tried it on ...