UART 16550和Linux内核中断

时间:2013-05-16 17:46:06

标签: c linux kernel uart

我正在尝试使用中断来查看UART 16550D中是否存在错误以及何时可以读取字符。

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。编译期间没有问题。

4 个答案:

答案 0 :(得分:0)

我分析了未触发中断处理程序的原因:

(1)确保传递给request_irq(virq,...)的第一个参数是硬件irq编号或虚拟irq编号。在某些平台上,硬件irq和request_irq(...)使用的数字之间存在映射。如果您的盒子上有映射,那么您错误地将处理程序连接到其他中断源;

(2)确保16550D上的中断屏蔽寄存器设置正确。我认为在16550D上应该有一个中断屏蔽寄存器,它可以屏蔽/取消屏蔽中断事件;

(3)检查request_irq(...)的返回值,确保中断连接成功。

希望以上帮助你。

答案 1 :(得分: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

答案 2 :(得分:0)

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

  

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

因此请求使用NULL的dev_id共享irq将无效。

答案 3 :(得分:0)

我知道这是一篇老文章,但以为我会给出答案。使用 gpio_to_irq 获取中断号。第三个参数确定何时发生中断。

irqNumber = gpio_to_irq(gpioUART);

// This next call requests an interrupt line
result = request_irq(irqNumber,       // The interrupt number requested
    (irq_handler_t) short_interrupt, // The pointer to handler function below
    IRQF_TRIGGER_FALLING,            // Interrupt on FALL edge ()
    "seri",                          // For /proc/interrupts identity
    NULL);                           // The *dev_id for shared interrupt