PCI串口

总线是一种传输信号的信道;总线是连接一个或多个导体的电器连线。总线由电气接口(关注硬件特性)和编程接口组成。对于后者需要了解电气接口


嵌入式开发中没有pci总线(PC)却用相应的拓展pci总线


只有PCI桥才能生成PCI总线



每个PCI设备由一个总线号、一个设备号、功能好确定。PCI规范允许一个系统最多拥有256条总线,每条总线最多带32个设备,但每个设备可以是最多8个功能的多功能板(如一个音频设备带一个CD-ROM驱动器)             (做驱动程序需要学设备规范,如USB规范)


PCI设备寻址

/proc/iomem描述了系统中所有的设备I/O在内存地址空间上的映射。我们来看地址从1G开始的第一个设备在/proc/iomem中是如何描述的:

40000000-400003ff : 0000:00:1f.1

这是一个PCI设备,40000000-400003ff是它所映射的内存空间地址,占据了内存地址空间1024bytes的位置,而0000:00:1F.1则是这个PCI外设的地址,它以冒号和逗号分隔4个部分,第一个16位表示域,第二个8位表示一个总线号,第三个5位表示一个设备号,最后是3位,表示功能号。


lspci查看系统pci设备

HostBridge连接系统总线和PCI总线(上图左边第一个PCI桥)

PCI总线只能由PCI桥产生

linux编号PCI桥是用深度优先算法遍历PCI桥的


配置寄存器

每个PCI设备都有一组固定格式的寄存器,即配置寄存器,配置寄存器由linux内核中的PCI初始化代码与驱动程序共同使用。内核在启动时负责对配置寄存器进行初始化,包括设置中断号和


配置空间

00H-01H Vendor ID 制造商标识     //用来标识PCI设备生产厂家的数值。intel的厂商标识为0x8086,全球厂商标识由PCI Special Interest Group来分配

02H-03H Device ID 设备标识         //用来标识设备的数值。Digital 21141快速以太设备的设备标识为0x0009

04H-05H Command命令寄存器

06H-07H Status状态寄存器

08H Revision ID 版本识别号寄存器

09H-0bH Class Code 分类代码寄存器

0cH Cache Line Size CACHE行长度寄存器

0dH Latency Timer 主设备延迟时间寄存器

0eH Header Type 头标类型寄存器

0fH Built-in-teset Register 自测试寄存器

10H-13H Base Address Resgister 0 基地址寄存器0

14H-17H Base Address Resgister 1 基地址寄存器1

18H-1bH Base Address Resgister 2 基地址寄存器2        //记录此设备使用的IO与内存空间的位置

1cH-19H Base Address Resgister 3 基地址寄存器3

30H-33H Expasion ROM Base Address 扩展ROM基地址

34H-3bH 保留

3cH Interrupt Line 中断线寄存器                //记录此设备使用的中断号

3dH Interrupt Pine 中断引脚寄存器       //记录此PCI设备使用的引脚号(A,B,C,D) 0表示不支持中断,非0表示支持中断

3eH Min_Gnt 最小授权寄存器

3fH Max_Lat 最大延迟寄存器



linux中,pci驱动使用struct_driver结构来描述

struct pci_driver{

................

const struct pci_device_id * id_table;               /*一个pci驱动程序支持很多设备,这些设备放入一个表id_table*/

int (*probe) (struct pci_dev * dev, const struct pci_device_id * id);       /*注册驱动时若某设备在表id_table中时执行probe函数*/

void (*remove) (struct pci_dev * dev);                      /*拔掉PCI设备调用*/

/*Device removed (NULL if not a hot-plug capable driver)*/

.............

}

一般只关注上面三个成员


pci_register_driver(struct pci_driver * drv)

int pci_enable_device(struct pci_dev * dev)/*使用PCI设备前需要使能*/

一个PCI设备最多可以实现6个地址区域,大多数PCI设备在这些区域实现I/O寄存器。linux提供了一组函数来获取这些区间的基地址:

pci_resource_start(struct pci_dev * dev, int bar)/*返回指定区域的起始地址,这个区域通过参数bar指定,范围从0-5,表示6个PCI区域中的一个*/

pci_resource_end(struct pci_dev * dev, int bar)/*返回指定区域的末地址*/


中断号存放于配置寄存器PCI_INTERRUPT_LINE中,驱动不必去检查它,因为从PCI_INTERRUPT_LINE中找到的值保证是正确的。如果设备不支持中断,寄存器PCI_INTERRUPT_PIN中的值是0,否则它是非零的值。但因为驱动开发者通常知道设备是否是支持终端,所以常常不需要访问PCI_INTERRUPT_PIN。


TTY(终端)是一类字符设备的统称:1.控制台;2.串口;3.伪终端

伪终端:由主-从两个成对的设备构成,当打开主设备时,对应的从设备随之打开,形成连接状态。输入到主设备的数据成为从设备的输出,输入到从设备的数据成为主设备的输出,形成双向管道。伪终端设备常用语远程登录服务器来建立网络和终端的关联。当通过telnet远程登录到另一台主机时,telnet进程与远程主机的telnet服务器相连接。telnet服务器使用某个主设备并通过对应的从设备与telnet进程相互通信



从硬件收到的数据向上通过tty驱动,进入tty线路规程,再进入tty核心,最后被用户获取。tty驱动可以直接和tty核心通讯,但是通常tty线路规程会修改在两者之间传送的数据。tty驱动不能直接和线路规程通信,甚至不知道它的存在,线路规程的工作是格式化从用户或者硬件收到的数据。这种格式化常常实现为一个协议,如PPP或Bluetooth



读操作

TTY驱动从硬件接收到数据后,负责把数据传递到TTY核心,TTY核心将从TTY驱动收到的数据缓存到一个tty_flip_buffer类型的结构中。该结构包含两个数据数组。从TTY设备接收到的数据被存储于第一个数组,当这个数组满,等待数据的用户将被通知。当用户从这个数组读数据时,任何从TTY驱动新来的数据将被存储在第2个数组。当第二个数组存满后,数据再次提交给用户,并且驱动又开始填充第1个数组,以此交替。


linux使用struct uart_driver描述串口驱动,它包含了串口设备的驱动名、设备名、设备号等信息

int uart_register_driver(struct uart_driver * drv)        /*串口驱动注册*/


uart_port用于描述一个UART端口(一个串口)的地址、FIFO大小/端口类型等信息

uart_ops定义了针对串口的一系列操作,包括发送、接收及线路设置等。


int uart_add_one_port(struct uart_driver * drv, struct uart_port * port)    /*串口核心层提供用来添加1个端口*/


操作流程:

1.定义一个uart_driver的变量,并初始化

2.使用uart_register_driver来注册这个驱动;

3.初始化uart_port和ops函数表;

4.调用uart_add_one_port()添加初始化好的uart_port

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值