UART设备驱动探究
1--Uart设备发送和接受数据的流程
1.1 tty设备发送数据的流程:
--tty核心从一个用户获取将要发送给一个tty设备的数据,[用户空间-->tty核心(tty_write)];
--tty核心将数据传递给tty线路规程驱动,[tty核心--->tty线路规程驱动(ldisc.write)];
--接着数据被传递到tty驱动,tty驱动将数据转换为可以发送给硬件的格式。[线路规程-->tty驱动(dirver.write)];
1.2 tty设备接受数据的流程:
--tty设备将数据提交给tty驱动,[tty_flip_buffer_push--->ldisc.read];
--tty驱动将数据提交给tty线路规程驱动,[ldisc.read--->tty_read];
--tty线路规程驱动将数据提交给tty核心,然后tty核心再提交给用户;[tty_read--->read];
2--uart驱动程序
2.1 特定UART相关的驱动程序结构
struct uart_driver {
struct module *owner; /* Module that owns this struct */
const char *driver_name; /* Name */
const char *dev_name; /* /dev node name such as ttyS */
/* ... */
int major; /* Major number */
int minor; /* Minor number */
/* ... */
struct tty_driver *tty_driver; /* tty driver */
};
2.2 UART驱动程序拥有的每个端口都存在uart_port结构的一个实例
struct uart_port {
spinlock_t lock; /* port lock */
unsigned int iobase; /* in/out[bwl]*/
unsigned char __iomem *membase; /* read/write[bwl]*/
unsigned int irq; /* irq number */
unsigned int uartclk; /* base uart clock */
unsigned char fifosize; /* tx fifo size */
unsigned char x_char; /* xon/xoff flow
/*...*/
}
2.3 struct uart_ops是每个UART驱动程序必须支持的物理硬件上可完成的操作的入口函数的集合
struct uart_ops {
uint (*tx_empty)(struct uart_port *); /* Is TX FIFO empty? */
void (*set_mctrl)(struct uart_port *,
unsigned int mctrl); /* Set modem control params */
uint (*get_mctrl)(struct uart_port *); /* Get modem control params */
void (*stop_tx)(struct uart_port *); /* Stop xmission */
void (*start_tx)(struct uart_port *); /* Start xmission */
/* ... */
void (*shutdown)(struct uart_port *); /* Disable the port */
void (*set_termios)(struct uart_port *,
struct termios *new,
struct termios *old); /* Set terminal interface
params */
/* ... */
void (*config_port)(struct uart_port *,
int); /* Configure UART port */
/* ... */
};
UART驱动程序为了将自身和内核联系起来,必须完成两个重要的步骤
(1)通过调用uart_register_dirver(struct uart_driver*);向串行核心注册;
(2)通过调用uart_add_one_port(struct uart_dirver*, struct uart_port*)注册其支持的每个端口。
2.串口发送数据
---------------------------------------------------
->write (应用层)
---------------------------------------------------
-->sys_write
(系统调用)
-->vfs_write
---------------------------------------------------
---->tty_write(**tty_fops)
(核心层)
---->do_tty_write(ld->ops->write, tty, file, buf, count);
---------------------------------------------------
------>n_tty_write(tty_ldisc_N_TTY)
(线路规程)
-------->c = tty->ops->write(tty, b, nr);
---------------------------------------------------
---------->uart_write
----------->uart_start
(tty统一驱动层)
------------>__uart_start
------------->port->ops->start_tx(port);
---------------------------------------------------
--------------->s3c24xx_serial_start_tx (tty设备)
在串口中断处理程序中发送数据。
---------------------------------------------------
//参考书籍--精通LINUX设备驱动开发--宋宝华