Real Time Systems: Notes

RTLinux (continued)

 

Setting up a Real-Time Clock Interrupt Handler

In sound.c, init_module does the following:

rtl_request_irq (8, intr_handler);
save_cmos_A = CMOS_READ(RTC_REG_A);
save_cmos_B = CMOS_READ(RTC_REG_B);
CMOS_WRITE(0x23, RTC_REG_A);  	/* 32kHz Time Base, 8192 Hz interrupt frequency */
ctemp = CMOS_READ(RTC_REG_B);
ctemp &= 0x8f;                	/* Clear */
ctemp |= 0x40;                	/* Periodic interrupt enable */
CMOS_WRITE(ctemp, RTC_REG_B); 
rtl_hard_enable_irq (8);
(void) CMOS_READ(RTC_REG_C);

The net effect is to:

To program the clock to interrupt at a different rate, you use a different value in the place of "0x23" above.

The handler is not installed directly at the hardware level. RTLinux installs its own handler at the lowest level. That handler in turn calls intr_handler.


RTLinux IRQ Handler Form

unsigned int intr_handler(unsigned int irq, struct pt_regs *regs) {
 	char data;
	char temp;
 	(void) CMOS_READ(RTC_REG_C);        /* clear IRQ */ 
...
	rtl_hard_enable_irq (8);
	return 0;
}

If you track down the definition of rtl_had_enable_irq you will eventually get to , in rtl_sync.h.

To understand why this all works, we need to understand something about the CMOS timer chip used on most PCs.

The following information is for people who like to understand how things work. One doesn't actually need to understand all this to reuse the RTLinux example code, if you are satisfied with cargo cult programming.


CMOS Timer


Linux CMOS Macros

It seems that the RTLinux code it careless about changing the CMOS register values. It does not mask interrupts while it is changing the values:

#define CMOS_WRITE(val, addr) ({ \
outb_p((addr),RTC_PORT(0)); \
outb_p((val),RTC_PORT(1)); \
})

Register A

For other values and their effects, see the table below:

RS bits
3210
Int/sec Period
0000 none none
0001 256 3.90625 ms
0010 128 7.8125 ms
0011 8192 122.070 μs
0100 4096 244.141 μs
0101 2048 488.281 μs
0110 1024 976.562 μs
0111 512 1.93125 ms
1000 256 3.90625 ms
1001 128 7.8125 ms
1010 64 15.625 ms
1011 32 31.25 ms
1100 16 62.50 ms
1101 8 125.0 ms
1110 4 250.0 ms
1111 2 500.0 ms

Note that the behaviors for the values 0x0001 and 0x0010 are anomalous.


Register B


The clock interrupt number is INT 0x70 (only coincidence that this is the same as the status register port number), which the PIC maps to PIC IRQ 8.


Register C


If you don't Register C, there will not be another interrupt

For further information see notes from http://www.geocities.com/SiliconValley/Campus/1671/docs/rtc2.html, reformatted to remove annoying Javascript side-effects, and HREF="rtc.html">http://www.geocities.com/SiliconValley/Campus/1671/docs/rtc.htm. The links precedingare actually to copies of these files which I have reformatted in HTML and cached locally to remove annoying Javascript side-effects.

© 1998, 2003 T. P. Baker. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without written permission.
$Id: rtlinux2.html,v 1.1 2003/10/17 12:34:01 baker Exp baker $