linux的串口子系统,Linux 串口子系统框架的总体说明

在前面几个章节,我们学习了tty子系统,并借助tty子系统完成了一个虚拟串口控制器驱动,并增加了两个虚拟串口。而在串口子系统中,为了让串口的开发更加简单,串口子系统又进行了一层框架搭建,构建了串口子系统,本章我们就介绍串口子系统框架。

老规矩,在了解一个子系统之前,我们先熟悉其数据结构及数据结构间的关联,这可有助于我们快速理解该子系统的大致结构,所要实现的功能有哪些等等。。。

相关数据结构说明

针对uart子系统,其又抽象了uart_driver、uart_port、uart_state、uart_ops几个数据结构,其中uart_driver也是表示一个串口控制器驱动的抽象,内部包含了tty_driver类型的成员变量,同时也包含了该串口控制器所支持的所有串口对应uart_state(可以理解为一个uart port相关的资源的数据结构);而uart_port是针对一个串口的抽象,其内部包含一个tty_port类型的成员变量,而uart_state可以理解该串口的资源信息,其完成了与uart_driver、uart_port、tty_struct的关联,其功能也类似于tty_struct,而uart_ops则定义了一个串口支持的操作接口。下面我们分别说明每一个数据结构的内容。

struct uart_driver

Uart_driver的定义如下,其中dev_name即为串口对应字符设备文件名的前缀,而major、minor则为串口对应主设备号以及次设备号起始位置(若不设置主设备号,则动态申请,一般不设置这两个变量);state为该串口控制器下串口的资源信息(如存储待发送数据的环形缓冲区等),tty_driver则为该串口对应的tty_driver类型的成员变量,该变量由串口子系统实现,因此无需驱动开发者初始化该变量(这也是uart子系统抽象后的一个好处,开发串口驱动时不再需要关注tty_driver的实现)

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

struct uart_state

该数据结构可以理解为串口的资源信息,如申请了一个环形缓冲区成员,用于存储待发送的数据;而port则为tty端口变量;uart_port则指向uart子系统定义的串口抽象数据结构。

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

struct uart_port

该数据结构是对uart端口的抽象

1.包含读写该端口寄存器相关的i/o及内存地址;

2.包含读写串口、设置串口termios的接口serial_in、seriall_out、set_termios

3.包含中断处理接口handle_irq(针对该接口,虽然在uart_port中定义但串口子系统的代码并没有对其做进一步使用,估计当时想把每一个串口中断处理也纳入uart_port中)

4.包含该串口端口的中断号、中断标签

5.state指向该uart_port对应的资源

6.ops指向该uart端口的操作接口(针对uart端口则需要实现ops中各函数指针)

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

struct uart_ops

该数据结构表示一个串口的操作接口,主要包含如下几个方向:tx_empty表示发送队列是否为空,也即该串口的存储发送数据的环形缓冲区是否为空;

stop_tx表示停止发送操作(可实现为关闭tx中断);

start_tx表示启动一次发送操作(如调用tty_driver->write执行发送操作时,完成发送数据拷贝后,则调用该start_tx,启动一次数据发送操作,该接口一般是使能发送中断);

stop_rx表示停止接收操作(一般是去使能接收中断),在uart_close接口中,会调用stop_rx、stop_tx停止收发操作;

throttle、unthrottle主要用于流控;

enable_ms主要等待操作完成;

startup主要用于启动串口的功能(如注册中断等)

set_termios用于设置该串口的termios信息,包括传输字节宽度、波特率等等,

而request_port申请该串口相关的io和内存资源以及端口的配置,针对端口的配置接口,config_port可以配置uart_port的type、flag等信息。目前针对io和内存的资源申请与释放,目前驱动并不是严格按照这两个接口定义,有一部分是在串口对应的probe接口中实现io和内存资源的申请并在remove接口中释放,这也就是设计人员提供了丰富而又全面的接口,但使用者却没有一一使用。

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

数据结构间的关联

下面是这几个数据结构与tty_port、tty_driver的关联,针对uart子系统只要我们掌握了如下关联图,

基本上针对uart子系统的概念就比较熟悉了。uart_driver主要是对tty_driver的包含(就像设备驱动模型中struct device_driver与struct xxx_device_driver的关系,uart_driver与tty_driver可简单理解为父类与子类之间的关系);

uart_state可以理解为uart_port的资源信息,此处我有点不解,个人感觉可以将uart_state和uart_port集合在一起,没必要整两个数据结构;

uart_port是对一个串口的抽象,其主要包含了一个串口的操作接口(struct uart_ops类型的成员变量,而使用uart子系统提供的接口完成串口驱动的开发时,一定要实现struct uart_ops,这是实现串口数据收发的关键);

串口子系统中已经定义struct tty_operation中各函数指针对应的函数,如uart_open、uart_write、uart_close等等,且uart_register_driver函数完成了tty_driver的申请及初始化,并注册至tty子系统中,因此这大大节省了驱动开发者的时间,只需调用uart_register_driver即可完成tty_driver的注册。

在调用uart_add_one_port时,即完成uart_state与uart_port的相互关联。

而在uart_open时,则完成tty_struct与uart_state的关联(tty_struct->driver_data=uart_state)

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

其实,针对uart子系统架构的实现,在我们上一章借助tty_register_driver创建虚拟串口后,对它的实现也可以快速理解,如我们在上一节中创建了数据结构virtual_tty_port,代表我们的虚拟串口,在该数据结构中定义了一个fifo用于存储待发送的数据,包含了tty_port。而在uart子系统中定义了uart_state、uart_port(uart子系统抽象了两个数据结构)

sgs_tc_news.php?req=5EnwWIVxbM4b9tTF1TH-KBY1RhV7zSluhNLFgBhYWZE=

而uart子系统针对串口的特性,抽象出来串口统一的操作接口(uart_open、uart_write、uart_close等等),并完成了统一的tty_driver、tty_port的申请、初始化、注册,而驱动开发者只需要实现uart_port->ops中各函数指针的设置即可,相对来说进一步简化了串口的开发流程。

以上即是本章的主要内容,下一章我们说明串口子系统的注册、注销以及读写操作流程,最后一章再借助uart子系统实现一个虚拟串口驱动。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值