全部博文(118)
分类: LINUX
2008-06-04 15:28:32
一个疑问:9260串口驱动是如何工作的?很奇怪,这两天我一直在考虑串口数据的中断接收数据,但是我在网上搜索基本上所有的帖子,采用的都是查询接收数据。逼得我今天不得不自己去看驱动。
看完之后我就发现一个很奇怪的现象:
我明明申请了7个uart口,但是为什么在/proc/interrupt中只看到一个中断?
dmesg:
<6>atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
<6>atmel_usart.1: ttyS1 at MMIO 0xfffb0000 (irq = 6) is a ATMEL_SERIAL
<6>atmel_usart.2: ttyS2 at MMIO 0xfffb4000 (irq = 7) is a ATMEL_SERIAL
<6>atmel_usart.3: ttyS3 at MMIO 0xfffb8000 (irq = 8) is a ATMEL_SERIAL
<6>atmel_usart.4: ttyS4 at MMIO 0xfffd0000 (irq = 23) is a ATMEL_SERIAL
<6>atmel_usart.5: ttyS5 at MMIO 0xfffd4000 (irq = 24) is a ATMEL_SERIAL
<6>atmel_usart.6: ttyS6 at MMIO 0xfffd8000 (irq = 25) is a ATMEL_SERIAL
cat /proc/interrupt
/mnt/flash2/home/yongtao $ cat /proc/interrupts
CPU0
1: 187090 AIC at91_tick, atmel_serial
12: 2 AIC atmel_spi.0
13: 11 AIC atmel_spi.1
20: 0 AIC ohci_hcd:usb1
21: 8621 AIC eth0
102: 1 GPIO mcp2515
Err: 0
为什么,后来我看了内核中的串口驱动代码之后,我才发现:
中断的请求:
static int atmel_startup(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
int retval;
/*
* Ensure that no interrupts are enabled otherwise when
* request_irq() is called we could get stuck trying to
* handle an unexpected interrupt
*/
UART_PUT_IDR(port, -1);
/*
* Allocate the IRQ
*/
printk("request uart irq %d\n",port->irq);
retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, "atmel_serial", port);
if (retval) {
printk("atmel_serial: atmel_startup - Can't get irq\n");
return retval;
}
中断的释放:
static void atmel_shutdown(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
/*
* Ensure everything is stopped.
*/
atmel_stop_rx(port);
atmel_stop_tx(port);
/*
* Shut-down the DMA.
*/
if (atmel_port->use_dma_rx) {
int i;
for (i = 0; i < 2; i++) {
struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
dma_unmap_single(port->dev, pdc->dma_addr, pdc->dma_size, DMA_FROM_DEVICE);
kfree(pdc->buf);
}
}
if (atmel_port->use_dma_tx) {
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
dma_unmap_single(port->dev, pdc->dma_addr, pdc->dma_size, DMA_TO_DEVICE);
}
/*
* Disable all interrupts, port and break condition.
*/
UART_PUT_CR(port, ATMEL_US_RSTSTA);
UART_PUT_IDR(port, -1);
/*
* Free the interrupt
*/
printk("release uart irq %d\n",port->irq);
free_irq(port->irq, port);
我们在dmesg中我们看到,不断的有:
<4>request uart irq 1
<4>release uart irq 1
也就是说,一旦没有数据进入的时候,内核马上就调用关闭函数关掉该串口。
后来我使用了一个非常简单的例子来测试一下:
int main(int argc, char *argv[])
{
int fd;
if((fd=open("/dev/ttyS1",O_RDWR))==-1)
{
printf("can't get device\n");
}
printf("just test\n");
while(1)
{
}
}
我奇怪的发现:
dmesg打出了如下的信息:
<4>request uart irq 6
<4>release uart irq 6
也就是说,你调用open打开该设备之后,如果你没有继续的动作,内核会马上该端口关上!!这也就是我们在/proc/interrupt中看不到其他中断的原因!!因为没有程序使用了这其他的几个串口。。或者即使你使用了,也没有长期的占用这个串口!!
明天一定要将串口设置为阻塞型,也就是如果应用程序不主动释放的话,就一直占用它!!