Real Time Systems: Notes |
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.
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.
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)); \ })
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.
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.
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 $ |