说明:
linux中的终端设备有以下几类:串口终端:ttySn,伪终端pty,控制终端ttyn,console.伪终端在linux中用pts(pseudo terminal slave)和ptmx(pseudo terminal master)实现.
控制终端用于登录linux,进行操作.在系统启动时,可以在初始化的时候通过console=device,options来配置控制终端,可以同时配置多个控制终端,当打开console时,返回的是最后一个console.
tty0是当前使用的控制终端别名.
tty驱动包括tty核心(tty_io.c),线路配置,tty具体驱动构成.
uart驱动是在tty_io之上通过serial_core再封装,将tty驱动转换成uart驱动.
变量:
struct ktermios{
c_cflag;//控制模式
c_iflag;//输入模式
c_oflag;//输出模式
c_lflag;//线路模式
c_cc;//控制字符
c_ispeed;//输入速率
c_ospeed;//输出速率
}struct tty_operations{
struct tty_struct *(*lookup)(struct tty_driver*driver,struct inode *inode,int idx);
int (install)(struct tty_driver driver,struct tty_struct *tty);
void (*remove)(struct tty_driver *driver ,struct tty_struct *tty);
int (*open)(struct tty_struct *tty,struct file *filep);
void (*close)(struct tty_struct *tty,struct file *filep);
int (*write)(struct tty_struct *tty,const char *buf,int len);
int (*put_char)(struct tty_struct *tty,unsigned char c);
int (*ioctl)(struct tty_struct *tty,struct file *filep,unsigned int cmd,unsigned int arg);
…
void (*set_temios)(struct tty_struct *tty,kermios*old);//设置termios
int (*tiocmget)(struct tty_struct *tty,struct file *filep);//设置modem函数
int (*tiocmset)(struct tty_struct *tty,struct file *filep,unsigned int set ,unsigned int clear);
}tty_struct{
struct kref kref;
struct device *dev;
struct tty_driver *driver;
struct tty_operations *ops;
…
struct ktermios *termios;
…
unsigned int receive_room;
tty_struct *link;
fasync_struct *fasync;
…
wait_queue_head_t write_wait;
wait_queue_head_t read_wait;
void * driver_data;
…
}tty_driver{
int magic;
struct kref kref;
struct cdev cdev;
struct module *owner;
const char * driver_name;//用于/proc/tty,sysfs中
const char *name;//设备节点
…
int major;
int minor_start;
int minor_num;
int num;
int type;
int subtype;
ktermios init_termios;
int flags;
tty_driver *other;//仅对pty驱动有用
ktermios **termios;
tty_struct **ttys;
void * tty_state;
…
const tty_operatios * ops;
}struct tty_port {
struct tty_struct tty; / Back pointer */
const struct tty_port_operations ops; / Port operations */
…
wait_queue_head_t open_wait; /* Open waiters */
…
unsigned long flags; /* TTY flags ASY_*/
unsigned char console:1; /* port is a console */
struct mutex mutex; /* Locking */
…
unsigned int close_delay; /* Close port delay */
unsigned int closing_wait; /* Delay for output */
…
struct kref kref; /* Ref counter */
};struct uart_ops{//此结构提供外设具体接口函数
unsigned int (tx_empty)(struct uart_port );
(*start_tx)
(*stop_tx)
(*send_xchar)
(*stop_rz)
…
}struct uart_port{//此结构用于描述外设资源
spinlock_t lock;
unsigned int iobase;
unsigned char __iomem *membase;
unsigned int irq;
unsigned int uartclk;
…
struct console *cons;
…
const struct uart_ops *ops;
void *private_data;
…
}struct uart_driver{//此结构用于在用户空间呈现接口
struct module *owner;
const char *dev_name;//设备节点名ttyxx
const char *driver_name;//驱动名
int nr;
struct console *cons;
struct uart_state *state;
struct tty_driver*tty_driver;
}
struct uart_state{
struct tty_port *port;
struct uart_port* uart_port;
…
}struct console{
char name[];
(*read)
(*write)
(*setup)
(*early_serup)
struct tty_driver*(*device)
void *data;
…
}
函数:
struct tty_driver* alloc_tty_driver(int lines);
int tty_register_driver(struct tty_driver*driver);
void tty_unregister_driver(struct tty_driver*driver);
void tty_register_device(struct tty_driver*driver,int index,struct tty_device*dev);
void tty_unregister_device(struct tty_driver*driver,int index);
void tty_set_operations(struct tty_driver*driver,struct tty_operations *ops);
用户空间函数
包括termios.h文件
int tcgetattr(int fd,struct termios*termios);
int tcsetattr(int fd,int operatios,struct termios*termios);
int cfsetospeed(struct termios *termios,speed_t speed);
int cfsetispeed(struct termios * termios,speed_t speed);//speed 是B0 B50 等
speed_t cfgetospeed(struct termios*termios);
speed_t cfgetispeed(struct termios *termios);int tcdrain(int fd);//等待所有输出被发送
int tcflush(int fd,int queue_selector);//flush输入/输出
int tcflow(int fd,int actios);//对输入/输出进行流控制
int tcsendbreak(int fd,int duration);//发送break字符uart驱动函数
int uart_register_driver(struct uart_driver*);
void uart_unregister_driver(struct uart_driver*);
int uart_add_one_port(struct uart_dirver*drv,struct uart_port *port);
int uart_remove_one_port(struct uart_driver *drv,struct uart_port*port);void register_console(struct console *con);
int unregister_console(struct console *con);
console_initcall(fn);//将cosole初始化函数放到系统的.con_initcall.init节中
扩展:
initcall节分为:initcall0.init,initcall.init …initcall7.init,对应的宏有pure_initcall(fn),core_initcall(fn)
postcore_initcall(fn),arch_initcall(fn),subsys_initcall(fn),fs_initcall(fn),device_initcall(fn),late_initcall(fn).
同时对于1~7节对应有sync版本pure_initcall_sync(fn)…
用法:
设备的资源
1 在设备的资源文件中定义uart的platform_device
struct resources xx_resources[]={
[0]={
.start=
.end=
.flags=
}
…
}
struct platform_device xx_uart_device={
.name=”xx_uart”;
.id=
.num_resources=ARRAY_SIZE(xx_resources);
.resources=&xx_resources;
}
2.在板子的初始化部分调用platform_device_register
platform_device_register(&xx_uart_device);驱动部分
定义uart_ops,uart_driver以及实现其中函数
xx_tx_empty(){ ... } xx_start_tx(){ ... } struct uart_ops xx_ops={ .tx_empty=xx_tx_empty; .start_tx=xx_start_tx; ... } struct uart_driver xx_uart_driver={ .dev_name="ttyxx" .driver_name="xxuart"; ... }
定义platform_driver
int xx_probe(struct platform_device *pdev){ ... 填充合适的uart_port结构 uart_add_one_port(&xx_uart_driver,&xx_uart_port);//此部分完成具体设备的功能添加,不同设备调用不同函数 platform_set_drvdata(pdev,xx_data); } int xx_remove(struct platform_device *pdev){ ... 进行必要的清除操作 uart_remove_one_port(&xx_uart_driver,&xx_uart_port); } struct platform_driver xx_platform_uart_driver={ .probe=xx_probe; .remove=xx_remove; .driver={ .name="xx_uart"; } } xx_init(void){ platform_driver_register(&xx_platform_uart_driver); } xx_exit(void){ platform_driver_unregister(&xx_platform_uart_driver); }
console实现
xx_setup(){//console setup 根据填充的port信息 调用uart_set_options(uart_port,console,baund,parity,bits,flow); } xx_write(){//console write } struct console xx_console={ .setup=xx_setup; .write=xx_write; } xx_console_init(){ 填充uart_port结构 register_console(&xx_console); }