Trouble with CMOS RTC (x86)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
jimka
Posts: 4
Joined: Sun Jan 24, 2010 8:55 am

Trouble with CMOS RTC (x86)

Post by jimka »

Hello, I've recently made a stab at OS development but I've seem to have hit a snag.

I'm trying to program the CMOS RTC, but I can seemingly only make the interrupt fire once. I've read that you have to read the 0xC register to make it fire multiple times but whatever I do, I cannot seem to make it work.

Here's the code I'm trying to make work:

Some defines

Code: Select all

#define CMOS 0x70
#define CMOSI 0x71
Helper functions

Code: Select all

uint8 get(uint8 part) {
	outb(CMOS, part);
	return inb(CMOSI);
}

void set(uint8 part, uint8 value) {
	outb(CMOS, part);
	outb(CMOSI, value);
}
Init code (remapped IRQ, IRQ8 = interrupt number 40)

Code: Select all

void Clock_Init() {
	ReadDate();

	// Install the RTC interrupt.
	InstallInterruptCallback(40, RTC_callback);
	uint8 regB = get(0xB) | 0x40;
	set(0xB, regB);
}
RTC callback

Code: Select all

void RTC_callback(registers_t regs) {
	static int ticks = 0;

	printf(".\n");
	ticks++;

	if(ticks % 1024) {
		if(c.second >= 60) {
			ReadDate();
		}

		ticks = 0;
	}

	// Read status register C so the interrupt will fire again. (not working atm).
	uint8 c = get(0xC);
}
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: Trouble with CMOS RTC (x86)

Post by Gigasoft »

This may be a stupid question, but do you remember to send an EOI in your ISR?
jimka
Posts: 4
Joined: Sun Jan 24, 2010 8:55 am

Re: Trouble with CMOS RTC (x86)

Post by jimka »

I thought I did, but I apparently had a minor bug in it:

Old one:

Code: Select all

void irq_handler(registers_t regs) {
	void (*irq)(registers_t) = func[regs.int_no];

	if(irq != 0) {
		irq(regs);
	} else {
		printf("Unhandled interrupt fired: %d.\n", regs.int_no);
	}

	if(regs.int_no > 31) {
		// Send EOI (End of Interrupt) signal to the PICs

		// If interrupt originated from the slave PIC, reset it.
		if(regs.int_no > 40) {
			outb(PICS, EOI);
		}

		// Reset the master PIC.
		outb(PICM, EOI);
	}
}
That should have been 'if(regs.int_no >= 40) ....', and this one also lead me to another piece of code that was in error, namely the one updating the clock. Thanks for suggestion.
Post Reply