新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > linux UART串口驱动开发文档

linux UART串口驱动开发文档

作者:时间:2012-09-06来源:网络收藏

顺带介绍开关中断接口:

static void w83697uart_start_tx(struct uart_port *port, unsigned int tty_start)

static void w83697uart_stop_tx(struct uart_port *port, unsigned int tty_stop)

函数: static void w83697uart_int(int irq, void *dev_id, struct pt_regs *regs)

描述: 中断处理函数,为3个使用系统外部中断的的的中断入口,其中必须处理的中断状态分为如下几种, 注意必须在处理中断时根据手册中的说明来清除中断,通常是读或写某些寄存器即可。

接收中断.

传送中断.

FIFO超时中断.

其它不具体处理的中断,必须读相应寄存器清中断.

函数: static void w83697uart_int2(int irq, void *dev_id, struct pt_regs *regs)

描述: 中断处理函数,为另外几个使用使用的GPIO中断入口,GPIO中断共享同一个系统中断向量, 必须根据GPIO的中断状态寄存器的相应位来判断对应的中断是属哪一个的,从而进行相应的处理,其实这个判断也是无所谓的,因为中断产生时传进来的参数已经含有了相应串口的参数, 在判断完中断产生的GPIO口后立即调用w83697uart_int2 完成具体的中断处理.

函数: static int w83697uart_startup(struct uart_port *port)

描述: 串口开启后的初始化函数,主要完成初始化配置,以及安装中断处理了函数,初始化配置包括打开中断使能标志。

函数: static void w83697uart_shutdown(struct uart_port *port)

描述: 串口关闭函数,清除配置,半闭中断.

函数: static void w83697uart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)

描述: 配置函数,经由上次调用下来,主要配制串口的波特率比,以及各种容错处理,在串口打开初始化时会被调用,在必变串口波特率/校验方式/停止位/传送位数等参数时会被调用.

5. 串口与上层的接口关联

文件: -2.4.21/drivers/serial/core.c

这一层接口是串口中的共用部分代码, 核心结构为struct uart_driver. 这一层上承TTY终端,下启串口底层,串口底层主要处理了与串口硬件相关的部分,并向上提供uart中间层向下的接口. Uart coar向下与底层的接口,通过一个static struct uart_ops amba_pops结构完成? 这个结构直接赋值给串口struct uart_amba_port amba_ports 的.ops成员,最后将串口的port加入到uart_driver当中完成关联, 通过uart_add_one_port加入.

static int __init w83697uart_init(void)

{

int ret, i;

ret = uart_register_driver(amba_reg);

if (ret == 0) {

for (i = 0; i _NR; i++)

uart_add_one_port(amba_reg, amba_ports[i].port);

}

return ret;

}

二. Linux的中断机制及中断共享机制.

前面讲到了有6个串口,除了w83697中的前三个串使用的是独立的系统外部中断之外,其它的在个串口是共享一个系统中断向量的,现在我们来看看多个中断是如何挂在一个系统中断向量表当中的,共享中断到底是什么样的一种机制?

进行分析代码可知,下的中断采用的是中断向量的方式,每一个中断对应一个中断描述数组当中的一项, 结构为struct irqdesc,其当中对应一成员结构为struct irqactionr 的成员action, 这个即表示此中断向量对应的中断处理动作,这里引用从网上下载的一幅图讲明中断向量表与中断动作之间的关系:

搜狗截图120906_14.jpg

struct irqaction {

void (*handler)(int, void *, struct pt_regs *);

unsigned long flags;

unsigned long mask;

const char *name;

void *dev_id;

struct irqaction *next;

};

从上面的结构体与图当中,我们就可以很清楚的看到,一个中断向量表可以对应一个irqaction,也可能对应多个由链表链在一起的一个链表irqaction, 这当中主要在安装中断的时候通过中断的标志位来决定:

安装中断处理,不可共享:

retval = request_irq(port->irq, w83697uart_int, 0, w83697_uart3, port);

安装中断处理,可共享:

retval = request_irq(port->irq, w83697uart_int2, SA_SHIRQ, w83977_uart5, port);

由上即可知,安装共享中断时,只须指定安装的中断标志位flag为SA_SHIRQ, 进入分析安装中断的处理可知,在安装时,会检测已经安装的中断是否支持共享中断,如果不支持,则新的中断安装动作失败;如果已经安装的中断支持共享中断,则还必须检测将要安装的新中断是否支持中断共享,如果不支持则安装还是会失败,如果支持则将此新的中断处理链接到此中断向量对应的中断动作处理链表当中.

在产生中断时,共享中断向量中对应的中断处理程序链表中的每一个都会被调用,依据链表的次序来,这样处理虽然会有影响到效率,但是一般情况下中断传到用户的中断处理服务程序中时,由用户根据硬件的状态来决定是否处理中断,所以能常情况下都是立即就返回了,效率的影响不会是大的问题.

三. Linux的软中断机制.

前面已经简单讲过了LINUX下的硬中断处理机制,其实硬中断的处理都由LINUX底层代码具体完成了,使用者一般在处理硬中断时是相当简单的,只须要用request_irq()简单的挂上中断即可,这里我们进一步介绍一下LINUX下的软中断机制,软中断机制相比起硬中断机制稍微复杂一些,而且在LINUX内核本身应用非常的广, 它作为一种软性的异步执行机制,只有深入理解了它才能灵活的运用.

之所以提到内核的softirq机制,主要是因为在串口中断也使用了这些机制,理解了这些机制就能更加明白串口驱动一些问题, 现在先提出几个问题如下:

前面提供到中断接收后数据,先放到flip缓冲区当中,这样让人很容易进一步想知道,中断处理的缓冲区的数据,用户进程读取串口时如何读到的?很明显中断处于内核空间,用户读取串口输入进程是在用户空间,中断缓冲区中的数据如何被处理到终端缓冲区中,供用户读取的?

linux操作系统文章专题:linux操作系统详解(linux不再难懂)

linux相关文章:linux教程




评论


相关推荐

技术专区

关闭