IRQ question

If you are new to OS Development, plan on spending some time here first before going into the other forums.

Moderator: Moderators

Post Reply
halofreak1990
Posts: 92
Joined: Thu May 27, 2010 8:54 pm
Location: Netherlands

IRQ question

Post by halofreak1990 » Mon Jun 07, 2010 9:56 pm

Hi, I've been searching around the web for some method to read from the RealTime Clock.
The code I found uses the RTC IRQ, which is 8, or 40, after remapping.
Anyways, I set a handler for it using setvect, and it simply won't fire.
I've read somewhere that I might be required to unmask the IRQ, or something,
but I couldn't find such code doing that for the keyboard or floppy to use as a reference.
I have the code waiting for the IRQ to fire, so my OS hangs right there.

Here's the code that sets up the IRQ, I pass it 40 as IRQ, which should work, based on the tut's IRQ mappings.

Code: Select all

void rtc_install(int irq)
{
    unsigned char status;

    write_register(0x0A, read_register(0x0A) | 0x0F); // important line here
    
    status = read_register(0x0B);
    status |=  0x02;             // 24 hour clock
    status |=  0x10;             // update ended interrupts
    status &= ~0x20;             // no alarm interrupts
    status &= ~0x40;             // no periodic interrupt
    bcd     =  !(status & 0x04); // check if data type is BCD
    write_register(0x0B, status);

    read_register(0x0C);

    setvect(irq, rtc_handler);
    
	while(!Interrupt); // pause till interrupt
}
I know the last line actually makes it hang, since its waiting for an interrupt which never fires, but I'm not gonna remove it, since it ensures that when I later down the road read out values, it's actually returning something.

pathos
Moderator
Posts: 97
Joined: Thu Jan 10, 2008 6:43 pm
Location: USA

Re: IRQ question

Post by pathos » Tue Jun 08, 2010 1:36 pm

To unmask an IRQ, you can do this:

Code: Select all

void enable_irq(int irq)
{
	if(irq == 16)
	{
		outportb(0x21, ~0xFF);
		outportb(0xA1, ~0xFF);
	}
	else if (irq >= 0 && irq < 8)
	{
		unsigned char irqmask = inportb(0x21);
		irqmask &= (1 << irq);
		outportb(0x21, irqmask);
	}
	else if (irq >7 && irq < 16)
	{
		unsigned char irqmask = inportb(0xA1);
		irqmask &= (1 << irq);
		outportb(0xA1, irqmask);
	}
}
Not sure if that will fix your problem however, but you can give it shot.

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Re: IRQ question

Post by Andyhhp » Tue Jun 08, 2010 4:55 pm

You will generally have to some programming of the RTC chip to tell it to fire.

I have no experience using it but in general, you can just insert an interrupt handler and expect everything else to be set up correctly.

~Andrew
Image

accelleon
Posts: 15
Joined: Mon Dec 07, 2009 3:41 am

Re: IRQ question

Post by accelleon » Wed Jun 09, 2010 2:45 am

Info on the RTC: http://wiki.osdev.org/RTC (MUST READ THIS)
Writing/reading the date to/from the RTC: http://wiki.osdev.org/CMOS#The_Real-Time_Clock (read this if you want to get the date from the RTC)

Hope that helps.

BTW wiki.osdev.org is an awesome resource for os developers :D

halofreak1990
Posts: 92
Joined: Thu May 27, 2010 8:54 pm
Location: Netherlands

Re: IRQ question

Post by halofreak1990 » Wed Jun 09, 2010 6:13 pm

I've been reading through the articles, and I have a question; do I need to set an interrupt to use the RTC?
Or would it be sufficient to read the RTC once, and increment the recieved data to simulate a clock?

Also, I've read about the NMI's and I'm thinking of designing a handler for those, since it would be nice to inform the user about a (non-fatal) hardware failure, so he/she can take the action required to correct this.

accelleon
Posts: 15
Joined: Mon Dec 07, 2009 3:41 am

Re: IRQ question

Post by accelleon » Thu Jun 10, 2010 12:17 am

no the interrupt doesn't need to be set.

to simulate a clock you could read from the RTC at startup, then use the PIT to increment the value.

the NMI only needs to be disabled when programming the RTC, however if you wish to have a handler for the NMI (which can be very useful in the even of hardware failures).

BTW: NMI that isn't caused by a memory read or write failure is an unrecoverable hardware failure. so if an NMI was triggered and it wasn't a memory failure, well then your gonna need to tell the user that they've got a faulty piece of hardware in their box.

halofreak1990
Posts: 92
Joined: Thu May 27, 2010 8:54 pm
Location: Netherlands

Re: IRQ question

Post by halofreak1990 » Tue Jun 15, 2010 10:58 pm

accelleon wrote:no the interrupt doesn't need to be set.
to simulate a clock you could read from the RTC at startup, then use the PIT to increment the value.
I've decided to ditch the irq handler for the RTC and read the values directly whenever I need.
Also, I check for the BCD flag and modify the returned variables as needed.
Now I only need to add checking for 24h/12h time and I'll be done with the clock.
accelleon wrote:BTW: NMI that isn't caused by a memory read or write failure is an unrecoverable hardware failure. so if an NMI was triggered and it wasn't a memory failure, well then your gonna need to tell the user that they've got a faulty piece of hardware in their box.
Better to tell the user something's wrong than to let them wonder why certain things don't work :wink:

EDIT: I read somewhere that, strangely, the RTC, though connected to IRQ8, will actually trigger IRQ 70h, perhaps I had to handle that one.
Also, fool that I was, failed to realize the OS from the tutorial here already has an NMI handler. I only need to modyfy it to display something useful instead of the standard "NMI Trap" message.

ehenkes
Posts: 34
Joined: Fri Jul 24, 2009 5:35 pm

Re: IRQ question

Post by ehenkes » Tue Jun 22, 2010 10:21 pm

https://prettyos.svn.sourceforge.net/sv ... nel/time.c

Code: Select all

uint8_t PackedBCD2Decimal(uint8_t PackedBCDVal)
{
    return ((PackedBCDVal >> 4) * 10 + (PackedBCDVal & 0xF));
}

Post Reply