2013-05-16 233 views
2

我想使用中断来查看UART 16550D是否有错误以及何时可以读取字符。UART 16550和Linux内核中的中断

的UART配置如下:

#define UART 0x03f8  // Endereço da Porta Serial - I (com1) 
#define UART_IER 1 
#define UART_LCR 3 
#define UART_LSR 5 
#define UART_DLL 0 /* Out: Divisor Latch Low */ 
#define UART_DLM 1 /* Out: Divisor Latch High */ 
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ 
#define UART_LSR_DR  0x01 /* Receiver data ready */ 
#define UART_RX  0 /* In: Receive buffer */ 
#define UART_TX  0 /* Out: Transmit buffer */ 

void UART_init(void){ 
    outb(0x80 , UART + UART_LCR);  
    outb(0x00 , UART + UART_DLM);  
    outb(0x60 , UART + UART_DLL);  
    outb(0x1f , UART + UART_LCR);  
    outb(0x07 , UART + UART_IER);   
    return; 
} 

和中断

irqreturn_t short_interrupt(int irq, void *dev_id){ 

     printk("INTERRUPT HAPPENED. WILL NOW RETURN\n"); 

     return 0; 
} 

static int seri_init(void){ 
     int result, i; 

     UART_init(); 

     request_irq(4, short_interrupt, SA_SHIRQ, "seri", NULL); 

     .... 

所以现在我只是想看看如果处理器被称为与否。 4被定义为我正在使用的虚拟框设置中的IRQ。

我想知道的是,这个设置有什么问题吗?在测试时,阅读和处理我正在阅读的内容时,我没有任何问题。事情是,处理程序永远不会被调用。

request_irq()的返回值是-22。编译期间没有问题。

+1

你的问题到底是什么? –

+0

哎呦,完全忘了那个。抱歉。 – Aleister

+0

您可能需要查看drivers/tty/serial/8250.c中的现有驱动程序(它也可以处理16550设备和其他类似设备)。中断处理程序是'serial8250_interrupt()'。如果您没有禁用该驱动程序,则由于与该驱动程序发生冲突,您可能无法获得您的中断。 –

回答

0

我为什么中断处理程序不会触发分析:

(1)确保传递给request_irq(virq,...)是硬件IRQ号或虚拟IRQ号的第一个参数。在某些平台上,硬件irq和request_irq(...)使用的数字之间存在映射关系。如果您的盒子上有映射,那么您错误地将您的处理程序连接到其他中断源; (2)确保16550D上的中断屏蔽寄存器设置正确。我认为16550D应该有一个中断屏蔽寄存器,它可以屏蔽/解除屏蔽中断事件; (3)检查request_irq(...)的返回值以确保中断已成功连接。

希望上面的帮助你。

+0

回报后,它给了我-22。我认为最接近的是来自linux/errno的无效参数,但我不知道它是否适用于此。但即使假设它是一个无效的论证,我在编译时也没有说什么。 – Aleister

0

变化

outb(0x80 , UART + UART_LCR);  
outb(0x00 , UART + UART_DLM);  
outb(0x60 , UART + UART_DLL);  
outb(0x1f , UART + UART_LCR);  
outb(0x07 , UART + UART_IER);  

outb(0x80 , UART + UART_LCR);  
outb(0x00 , UART + UART_DLM);  
outb(0x60 , UART + UART_DLL);  
outb(0x07 , UART + UART_IER); // Set IER before clearing DLAB bit in LCR 
outb(0x1f , UART + UART_LCR);  
// You may also need 
outb(8 , UART + 4); // Some systems use this as a master interrupt enable 
0

-22是EINVAL,我想这是因为NULL最后一个参数。此页面:http://www.makelinux.net/books/lkd2/ch06lev1sec3说:

第五个参数dev_id主要用于共享中断线。当一个中断处理程序被释放(稍后讨论)时,dev_id提供了一个唯一的cookie,以允许从中断线中只删除所需的中断处理程序。没有这个参数,内核就不可能知道在给定的中断线上删除哪个处理程序。 您可以在这里NULL如果传递线路不共享的,但如果你的中断线路共享

所以请求共享的IRQ清零室内用的dev_id将无法正常工作,你必须通过一个唯一的cookie。