说明:
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); }