Title: Handling a UART interrupt
1Handling a UART interrupt
- A look at some recent changes in the Linux
kernels programming interface for
device-interrupts
2The new anchor cluster
- To reduce contention for CS workstations that
have null-modem cables attached, we are bringing
online an additional cluster of eight servers
you access them remotely
anchor00
anchor01
anchor02
anchor03
anchor04
anchor05
anchor06
anchor07
Thanks to overnight efforts by Alex Fedosov and
our CS support-team! ?
3LDD3 kernel 2.6.10
- Our text Linux Device Drivers (3rd Ed) is
published by OReilly in February 2005 - The kernel version it covers is 2.6.10
- But in our classroom we are using a more recent
version of the kernel (i.e., 2.6.22.5) which was
released in mid-August 2007 - Various changes (improvements) are now
implemented (and differ from LDD3 book)
4Example 1
- Our textbook shows the prototype for a
device-drivers interrupt service routine - irqreturn_t isr( int irq, void dev_id, struct
pt_regs regs ) - But this has changed in kernel 2.6.22.5 to
- Irqreturn_t isr( int irq, void dev_id )
- What prompted the kernel developers to remove
that third function-argument? - Just a guess, but probably it was because
programmers were not actually using it
5Example 2
- The kernels header-files ltasm/signal.hgt provided
symbolic names for important interrupt-related
constants in 2.6.10 - define SA_SHIRQ 0x04000000
- Such definitions, formerly replicated for each
supported CPU architecture, have now been
consolidated (and renamed) in the kernel
header-file ltlinux/interrupt.hgt - define IRQF_SHARED 0x00000080
6Consequences
- If you try to apply the textbook discussion about
interrupt-handlers to your LKMs for this class,
the compiler will generate error messages and/or
warning messages - So you will need to use the new kernels
interfaces, not documented in our textbook - Maybe you can locate an online tutorial, or look
at other device-drivers source-code
7Our uartintr.c module
- We have written a kernel module that you can
study (and experiment with) showing an
interrupt-handler for the UART device that we
created purely for demonstration purposes using
kernel version 2.6.22.5 - Obviously you would need to modify it if you
wanted to use an interrupt-handler in your
solution for our courses Project 2
8Modules components
The LKM layout
modules payload is just a single
callback-function that will handle a
UART interrupt
The isr function
registers the isr and then enables the UART
device to generate interrupt-signals
init
the usual pair of module-administration
functions
exit
disables the UARTs interrupt-signals and
then unregisters this modules isr
9Interrupt Identification Register
7 6 5 4
3 2 1 0
0
0
highest priority UART interrupt still
pending
00 FIFO-mode has not been enabled 11
FIFO-mode is currently enabled
highest 011 receiver line-status
010 received data ready 100 character
timeout 001 Tx Holding Reg empty
000 modem-status change lowest
1 No UART interrupts are pending 0 At least
one UART interrupt is pending
10An interrupt service routine
- Whenever the UART receives a new byte of data, it
will transmit it back to the sender
include ltlinux/interrupt.hgt include
ltasm/io.hgt define UART_BASE 0x03F8 irqreturn_t
my_uart_isr( int irq, void dev_id
) int intr_identify inb( UART_BASE 2 )
0x0F if ( intr_identify 0x01 ) return
IRQ_NONE if ( intr_identify 0x04 ) //
a new character has arrived outb( inb(
UART_BASE ), UART_BASE ) return IRQ_HANDLED
11Installing the isr()
- Here is how your module asks the kernel to
execute your UART interrupt-handler
define UART_IRQ 4 // signal-lines number to
the IO-APIC char modname uartintr //
kernel displays this in /proc/interrupts
static int __init my_init( void ) if (
request_irq( UART_IRQ, my_uart_isr,
IRQF_SHARED, modname, modname ) lt 0 ) return
EBUSY // your code to enable the UARTs
interrupts goes here return 0 // SUCCESS
12Interrupt Enable Register
7 6 5 4
3 2 1 0
0
0
0
0
Modem Status change
Rx Line Status change
THR is empty
Received data is available
If enabled (by setting the bit to 1), the UART
will generate an interrupt (bit 3) whenever
modem status changes (bit 2) whenever a
receive-error is detected (bit 1) whenever the
transmit-buffer is empty (bit 0) whenever the
receive-buffer is nonempty Also, in FIFO mode,
a timeout interrupt will be generated if
neither FIFO has been serviced for at least
four character-clock times
13FIFO Control Register
7 6 5 4
3 2 1 0
RCVR FIFO trigger-level
reserved
reserved
DMA Mode select
XMIT FIFO reset
RCVR FIFO reset
FIFO enable
00 1 byte 01 4 bytes 10 8 bytes 11 14
bytes
NOTE DMA is unsupported for the UART on our
systems
Writing 1 empties the FIFO, writing 0 has no
effect
Writing 0 will disable the UARTs FIFO-mode,
writing 1 will enable FIFO-mode
14Modem Control Register
7 6 5 4
3 2 1 0
0
0
0
LOOP BACK
OUT2
OUT1
RTS
DTR
Legend DTR Data Terminal Ready (1yes,
0no) RTS Request To Send (1yes, 0no)
OUT1 not used (except in loopback mode)
OUT2 enables the UART to issue interrupts
LOOPBACK-mode (1enabled, 0disabled)
15UART initialization
- Here is code that initializes the UART (its
baud-rate and data-format) and enables it to
generate character received interrupts
// initialize the UART device for the desired
demo operations outb( 0x01, UART_BASE 1 ) //
issue RDR interrupts outb( 0x00, UART_BASE 2
) // turn off FIFO-mode outb( 0x80, UART_BASE
3 ) // SET DLAB1 outw( 0x0001, UART_BASE
) // DIVISOR_LATCH 1 outb( 0x03, UART_BASE
3 ) // data-format is 8-N-1 outb( 0x0B,
UART_BASE 4 ) // DSR1, RTS1, OUT21
16Disabling UART interrupts
- Here is code that disables any more UART
interrupts, so that your modules cleanup can
safely remove your interrupt-handler
static __exit my_exit( void ) // disable
any further UART interrupt-requests outb( 0x00,
UART_BASE 1 ) // INTERRUPT_ENABLE outb( 0x00,
UART_BASE 4 ) // MODEM_CONTROL // remove
your UART interrupt-service routine free_irq(
UART_IRQ, modname )
17In-class exercise
- Try running our trycable.cpp application on an
adjacent workstation after you have downloaded,
compiled, and installed our uartintr.c
demo-module - What do you see on the two screens?
- Tonights class ends early -- so that you can
attend the ACM Chapters Pizza Night