1 / 17

Handling a UART interrupt

Handling a UART interrupt. A look at some recent changes in the Linux kernel’s programming interface for device-interrupts . The new ‘anchor’ cluster.

Télécharger la présentation

Handling a UART interrupt

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.


Presentation Transcript

  1. Handling a UART interrupt A look at some recent changes in the Linux kernel’s programming interface for device-interrupts

  2. The 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! 

  3. LDD3: kernel 2.6.10 • Our text “Linux Device Drivers (3rd Ed)” is published by O’Reilly 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., which was released in mid-August 2007 • Various changes (improvements) are now implemented (and differ from LDD3 book)

  4. Example 1 • Our textbook shows the prototype for a device-driver’s interrupt service routine: irqreturn_t isr( int irq, void *dev_id, struct pt_regs *regs ); • But this has changed in kernel 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

  5. Example 2 • The kernel’s header-files <asm/signal.h> 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 <linux/interrupt.h>: #define IRQF_SHARED 0x00000080

  6. Consequences • 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” kernel’s interfaces, not documented in our textbook • Maybe you can locate an online tutorial, or look at other device-drivers’ source-code

  7. Our ‘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 • Obviously you would need to modify it if you wanted to use an interrupt-handler in your solution for our course’s Project #2

  8. Module’s components The LKM layout module’s ‘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 UART’s interrupt-signals and then unregisters this module’s ‘isr’

  9. Interrupt 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

  10. An interrupt service routine • Whenever the UART receives a new byte of data, it will transmit it back to the sender #include <linux/interrupt.h> #include <asm/io.h> #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; }

  11. Installing the ‘isr()’ • Here is how your module asks the kernel to execute your UART interrupt-handler: #define UART_IRQ 4 // signal-line’s 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 ) < 0 ) return –EBUSY; … // your code to enable the UART’s interrupts goes here … return 0; // SUCCESS }

  12. Interrupt 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

  13. FIFO 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 UART’s FIFO-mode, writing 1 will enable FIFO-mode

  14. Modem Control Register 7 6 5 4 3 2 1 0 0 0 0 LOOP BACK OUT2 OUT1 RTS DTR Legend: DTR = Data Terminal Ready (1=yes, 0=no) RTS = Request To Send (1=yes, 0=no) OUT1 = not used (except in loopback mode) OUT2 = enables the UART to issue interrupts LOOPBACK-mode (1=enabled, 0=disabled)

  15. UART 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 DLAB=1 outw( 0x0001, UART_BASE ); // DIVISOR_LATCH = 1 outb( 0x03, UART_BASE + 3 ); // data-format is 8-N-1 outb( 0x0B, UART_BASE + 4 ); // DSR=1, RTS=1, OUT2=1

  16. Disabling UART interrupts • Here is code that disables any more UART interrupts, so that your module’s ‘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 ); … }

  17. In-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? • Tonight’s class ends early -- so that you can attend the ACM Chapter’s Pizza Night

More Related