我正在尝试使用中断来查看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。编译期间没有问题。
答案 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