tty目录下的8250指的是intel的8250系列串口芯片驱动目录;8250系列包括8250,16450,16450A等。
【struct uart_port解析】
flag 串口属性标志,以下是解释
#define UPF_FOURPORT 4端口串口卡,8250系列
#define UPF_SAK 当串口接收到break信号时终止在当前虚拟终端上运行的所有进程(包括X窗口)。这个组合键被称为“安全访问键“(SAK).
#define UPF_SPD_MASK 波特率掩码
#define UPF_SPD_HI 当设置波特率的参数非法时,默认其为57600
#define UPF_SPD_VHI 当设置波特率的参数非法时,默认其为115200
#define UPF_SPD_CUST 当期望波特率为38400时,如果UPF_SPD_HI和UPF_SPD_VHI同时被指定,则波特率除数由port->custom_divisor指定,这个用不到
#define UPF_SPD_SHI 当设置波特率的参数非法时,默认其为230400
#define UPF_SPD_WARP 当设置波特率的参数非法时,默认其为460800
#define UPF_SKIP_TEST 调过检测串口是否存在,当前只有8250系列驱动在用
#define UPF_AUTO_IRQ 串口中断号由port->ops->config_port()自动探测
#define UPF_HARDPPS_CD 支持硬件秒脉冲检测
#define UPF_LOW_LATENCY 串口接收到数据后是否立即传递到line discipline处理
#define UPF_BUGGY_UART 古怪的串口???一般不用
#define UPF_NO_TXEN_TEST 不进行传输使能检测
#define UPF_MAGIC_MULTIPLIER 波特率除数计算时不通过uart_get_divisor()来获得,而是直接指定
#define UPF_CONS_FLOW 具有流控功能
#define UPF_SHARE_IRQ 与其他设备共享中断号,未用到
#define UPF_EXAR_EFR 串口为8250系列XR17D15x芯片,它的Extended Features Register位置和普通8250系列不一样
#define UPF_BUG_THRE 8250系列串口,存在THRE的bug
#define UPF_FIXED_TYPE 串口类型是固定的,否则由port->ops->config_port()来探测
#define UPF_BOOT_AUTOCONF 是否在串口注册时自动配置(调用port->ops->config_port())
#define UPF_FIXED_PORT 串口类型属性注册后就不可以改变
#define UPF_DEAD 置位表示串口已通过uart_remove_one_port()移除,uart_add_one_port()时该位清除
#define UPF_IOREMAP 串口访问资源需要进行IOREMAP操作
#define UPF_CHANGE_MASK 串口属性类型变更时flag标志需变更的比特位掩码
#define UPF_USR_MASK 用户可以修改的比特位掩码
mctrl 当前串口控制状态,主要由串口驱动核心在使用,他的标志位如下
TIOCM_LE ???
TIOCM_DTR 终端设备已准备好
TIOCM_RTS 终端设备请求发送数据
TIOCM_ST
TIOCM_SR
TIOCM_CTS 允许终端设备发送数据过来
TIOCM_CAR / TIOCM_CD 线路上已检测到载波
TIOCM_RNG / TIOCM_RI 通知终端设备,modem已被呼叫
TIOCM_DSR modem已准备好
TIOCM_OUT1 / TIOCM_OUT2 这个啥用???
TIOCM_LOOP modem处于回环模式
timeout 关断串口时等待数据发送完成的时间
type 串口类型,serial_core.h中定义,比如PORT_ATMEL系列为49
ops 实现硬件操作的驱动方法,写串口驱动大部分代码在此处
custom_divisor 计算波特率除数时如果指定的波特率非法则直接使用custom_divisor, 具体参见uart_get_divisor()
line 串口序号,跟打印信息,设备号等相关
mapbase ioremap映射的地址参数,物理地址
membase ioremap之后的虚拟地址,所有对串口资源的访问都是用改地址,使用readw()/writew()
iobase 直接IO指令访问时传递的地址参数,intel X86系列有此功能,但是ARM架构都是通过内存映射访问
serial_in 传统的串口资源访问方法,调用serial_port_in()访问,驱动可以自己使用
serial_out 传统的串口资源访问方法,调用serial_port_out()访问,驱动可以自己使用
set_termios 设置串口的属性,现在只有8250系列芯片还在使用,该功能现在由struct uart_ops的set_termios实现
handle_irq 串口中断处理函数,现在只有8250系列芯片还在使用,在该函数外面再包一层注册中断函数,多此一举,所以最好的方法是不用此方法。
pm 8250系列芯片独享,其他驱动在struct uart_ops的pm方法里实现
irq 中断号,既可以指定,也可以动态探测得到,取决于系统架构
irqflags 中断函数的标志位,注册中断时使用
uartclk 串口输入时钟频率
fifosize fifo大小,一般串口都带有fifo吧。。
x_char 保存需要发送的XON/XOFF字符时,一般上层调用port->ops->send_xchar,如果没提供该方法则调用port->ops->start_tx(),这样一来就基本上是在中断函数中查询是否需要发送XON/XOFF字符
regshift 寄存器序号之间的地址偏移,一般设为4,但是这个用处不大
iotype 串口资源的类别,有UPIO_PORT、UPIO_HUB6、UPIO_MEM、UPIO_MEM32、UPIO_AU、UPIO_TSI, UPIO_PORT和UPIO_HUB6都是IO访问型,UPIO_MEM、UPIO_MEM32是需要内存映射的,后三个坑爹吧,应该也是内存映射的,为啥要独立出来???
unused1 确实没用到,那么驱动可以用来干自己的小九九
read_status_mask 串口工作状态读取掩码,掩码外的状态不处理,因此显然这个成员是驱动用的
ignore_status_mask uart_insert_char()读取数据时需要忽略哪些状态位
state 指向struct uart_state,uart_state用于汇总上下层的数据结构
icount 串口统计计数,驱动要用到的
cons 当串口需要作为Printk系统打印控制台时用到
sysrq 执行sysrq操作时的timeout时间,串口驱动核心自己使用,当前确定为5s,底层驱动不要赋值
dev 设备驱动模型表示
hub6 8250系列6端口串口卡,指定其端口序号
suspended 串口是否处于休眠状态,驱动别去碰他
irq_wake 串口是否处于中断待唤醒状态,没怎么用
unused 这个驱动可以用,但是不推荐
private_data 驱动特定的数据结构,貌似大家都没用
lock 自旋锁,驱动和串口核心都用,注意互斥访问
struct uart_ops驱动操作方法:
tx_empty 传输缓冲区是否为空
set_mctrl 设置串口控制状态
get_mctrl 获取串口控制状态
stop_tx 停止传输数据
start_tx 启动传输数据
send_xchar 发送XON/XOFF字符
stop_rx 停止接收数据
enable_ms 允许modem状态中断
break_ctl break信号控制
startup 启动串口所需的软件资源,比如定时器、中断注册等
shutdown 关断串口,与startup相反
flush_buffer 清空传输缓冲区
set_termios 设置串口工作模式
set_ldisc 进行线路规程相关设置
pm 电源管理操作
set_wake ???
type 查询串口类别,返回字符串
release_port 释放串口注册的软件资源
request_port 申请串口使用的软件资源
config_port 端口配置
verify_port 验证用户层的设置是否正确
ioctl 用户ioctl操作,一般底层驱动不需要实现了,因为uart层已经实现了大部分的命令
poll_put_char 以查询方式发送数据
poll_get_char 以查询方式接收数据
uart接口API
uart_add_one_port
1、通过struct uart_state和struct tty_port挂接;
2、配置端口硬件port->ops->config_port、port->ops->set_mctrl;
3、向设备驱动核心注册;
uart_register_driver
1、创建并初始化struct uart_driver的上层代表struct tty_driver;
2、注册设备号(后续用户操作时根据设备号就能找到对应的驱动);
3、链接到tty驱动的单链表中;
struct ktermios的标志位说明
struct ktermios {
tcflag_t c_iflag; /*input mode flags */
tcflag_t c_oflag; /*output mode flags */
tcflag_t c_cflag; /*control mode flags */
tcflag_t c_lflag; /*local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
}
c_iflag:输入模式标志,控制终端输入方式,具体参数如表1所示。
表1 c_iflag参数表
键 值 |
说 明 |
IGNBRK |
忽略BREAK键输入 |
BRKINT |
如果设置了IGNBRK,BREAK键输入将被忽略 |
IGNPAR |
忽略奇偶校验错误 |
PARMRK |
标识奇偶校验错误 |
INPCK |
允许输入奇偶校验 |
ISTRIP |
去除字符的第8个比特 |
INLCR |
将输入的NL(换行)转换成CR(回车) |
IGNCR |
忽略输入的回车 |
ICRNL |
将输入的回车转化成换行(如果IGNCR未设置的情况下) |
IUCLC |
将输入的大写字符转换成小写字符(非POSIX) |
IXON |
允许输入时对XON/XOFF流进行控制 |
IXANY |
输入任何字符将重启停止的输出 |
IXOFF |
允许输入时对XON/XOFF流进行控制 |
IMAXBEL |
当输入队列满的时候开始响铃 |
c_oflag:输出模式标志,控制终端输出方式,具体参数如表2所示。
表2 c_oflag参数
键 值 |
说 明 |
OPOST |
处理后输出 |
OLCUC |
将输入的小写字符转换成大写字符(非POSIX) |
ONLCR |
将输入的NL(换行)转换成CR(回车)及NL(换行) |
OCRNL |
将输入的CR(回车)转换成NL(换行) |
ONOCR |
第一行不输出回车符 |
ONLRET |
不输出回车符 |
OFILL |
发送填充字符以延迟终端输出 |
OFDEL |
以ASCII码的DEL作为填充字符,如果未设置该参数,填充字符为NUL |
NLDLY |
换行输出延时,可以取NL0(不延迟)或NL1(延迟0.1s) |
CRDLY |
回车延迟,取值范围为:CR0、CR1、CR2和 CR3 |
TABDLY |
水平制表符输出延迟,取值范围为:TAB0、TAB1、TAB2和TAB3 |
BSDLY |
空格输出延迟,可以取BS0或BS1 |
VTDLY |
垂直制表符输出延迟,可以取VT0或VT1 |
FFDLY |
换页延迟,可以取FF0或FF1 |
c_cflag:控制模式标志,指定终端硬件控制信息,具体参数如表3所示。
表3 c_cflag参数
键 值 |
说 明 |
CBAUD |
波特率(4+1位)(非POSIX) |
CBAUDEX |
附加波特率(1位)(非POSIX) |
CSIZE |
字符长度,取值范围为CS5、CS6、CS7或CS8 |
CSTOPB |
设置两个停止位 |
CREAD |
使用接收器 |
PARENB |
使能校验 |
PARODD |
置1使用奇校验,置0使用偶校验 |
HUPCL |
关闭设备时挂起 |
CLOCAL |
忽略调制解调器线路状态 |
CRTSCTS |
使用RTS/CTS流控制 |
CMSPAR |
使用MARK/SPACE校验方式 |
c_lflag:本地模式标志,控制终端编辑功能,具体参数如表4所示。
表4 c_lflag参数
键 值 |
说 明 |
ISIG |
当输入INTR、QUIT、SUSP或DSUSP时,产生相应的信号 |
ICANON |
使用标准输入模式 |
XCASE |
在ICANON和XCASE同时设置的情况下,终端只使用大写。 |
ECHO |
显示输入字符 |
ECHOE |
如果ICANON同时设置,ERASE将删除输入的字符 |
ECHOK |
如果ICANON同时设置,KILL将删除当前行 |
ECHONL |
如果ICANON同时设置,即使ECHO没有设置依然显示换行符 |
ECHOPRT |
如果ECHO和ICANON同时设置,将删除打印出的字符(非POSIX) |
TOSTOP |
向后台输出发送SIGTTOU信号 |
c_cc[NCCS]:控制字符,用于保存终端驱动程序中的特殊字符,如输入结束符等。c_cc中定义了如表5所示的控制字符。
表5 c_cc支持的控制字符
宏 |
说 明 |
宏 |
说 明 |
VINTR |
Interrupt字符 |
VEOL |
附加的End-of-file字符 |
VQUIT |
Quit字符 |
VTIME |
非规范模式读取时的超时时间 |
VERASE |
Erase字符 |
VSTOP |
Stop字符 |
VKILL |
Kill字符 |
VSTART |
Start字符 |
VEOF |
End-of-file字符 |
VSUSP |
Suspend字符 |
VMIN |
非规范模式读取时的最小字符数 |