微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux下的串口总线驱动(二)

Linux下的串口总线驱动(二)

时间:11-22 来源:互联网 点击:

了write_room外,还有其他一些缓冲函数,例如TTY层ops中chars_in_buffer,也就是uart_chars_in_buffer,当tty核心在tty驱动程序的写缓冲区中还有多少个需要传输的字符时调用该函数。

除此之外TTY层ops中还有三个回调函数,用来刷新驱动程序保存的任何数据,并不一定要实现,但是如果tty驱动程序能在发送给硬件前缓冲数据,还是推荐实现它们的,它们分别是flush_buffer,wait_until_sent,flush_buffer。

回顾一下,我们在TTY层的ops中,主要讲了write,set_termiox, tiocmget,tiocmset,ioctl,五个函数,还简单介绍了write_room,chars_in_buffer,flush_buffer,wait_until_sent,flush_buffer五个函数。到目前为止,我们已经分析好了uart_register_driver函数,现在该分析uart_add_one_port函数了。

int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)

{

struct uart_state *state;

struct tty_port *port;

int ret = 0;

struct device *tty_dev;

BUG_ON(in_interrupt());

if (uport->line >= drv->nr)

return -EINVAL;

state = drv->state + uport->line;

port = &state->port;

mutex_lock(&port_mutex);

mutex_lock(&port->mutex);

if (state->uart_port) {

ret = -EINVAL;

goto out;

}

state->uart_port = uport;

state->pm_state = -1;

uport->cons = drv->cons;

uport->state = state;

//如果这个端口是控制台,那么这个锁就已经初始化了

if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {

spin_lock_init(&uport->lock);

lockdep_set_class(&uport->lock, &port_lock_key);

}

uart_configure_port(drv, state, uport); //配置端口

tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);//注册端口

if (likely(!IS_ERR(tty_dev))) {

device_init_wakeup(tty_dev, 1);

device_set_wakeup_enable(tty_dev, 0);

} else

printk(KERN_ERR "Cannot register tty device on line %d\n",

uport->line);

//确保UPF_DEAD没有被置位

uport->flags &= ~UPF_DEAD;

out:

mutex_unlock(&port->mutex);

mutex_unlock(&port_mutex);

return ret;

}

对于uart_add_one_port,我们发现其中最核心的一句代码就是tty_register_device,仅有tty_driver是不够的,驱动必须依附于设备,tty_register_device函数用于注册关联于tty_driver的设备。

总结下,TTY层的uart_register_driver和uart_register_port最终调用线路规程的tty_register_driver和tty_register_device。而tty_register_driver和tty_register_device的实现在线路规程中。

对于TTY驱动主要涉及如下几个重要结构体,struct tty_struct包含了和打开的tty相关的所有状态信息。其中一个重要的成员就是struct tty_bufhead buf,它是数据收集和处理机制的中枢,其定义如下

struct tty_bufhead {

struct delayed_work work;

spinlock_t lock;

struct tty_buffer *head;

struct tty_buffer *tail;

struct tty_buffer *free;

int memory_used;

};

另一个重要结构体是struct tty_driver,它规定了tty驱动程序和高层之间的编程接口。在我们这个TTY层,由uart_register_driver下的tty_register_driver注册入内核,其中这个结构体中的成员部分是通过拷贝uart_driver中的参数得到。

好了,对于TTY层驱动,一般而言,我们需要完成如下两个任务:

其一,终端设备驱动模块的加载函数和卸载函数,完成注册和注销tty_driver,初始化和释放终端设备对应的tty_driver结构体成员和硬件资源。

其二,实现tty_operations结构体中的一系列成员函数,主要的是实现open()、close()、 write()、 tiocmget()、 tiocmset()。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top