Uart体系结构

UART设备驱动可以使用tty驱动的框架来实现,但是因为串口之间有共性,所以Linux在tty接口上封装了一层(serial core)。后面我们再拿一篇文章来解释tty驱动,tty其实就是各种终端设备,串口其实也是终端设备。

驱动工程师没必要关心上层的流程,只需注册一个uart_driver,并按硬件规范将对应接口函数完成就可以了。

上图我们只需要实现xxx_uart.c ,  而我们实现所需要的结构体和函数接口就是由serial_core.c提供。接下来我们来看一下对应的结构体和接口函数。

重要结构体

内核版本:4.20.12

  • uart_driver

struct uart_driver {struct module    *owner;const char    *driver_name;const char    *dev_name; //设备名,即dev下的节点名int       major;int       minor;int       nr;struct console    *cons;//console配置,串口作为console时才需要//私有的,底层驱动把它初始化为NULL即可struct uart_state  *state;struct tty_driver  *tty_driver;
};

串口设备也是字符设备,所以看到很多字符设备相关的,console就是控制台,我们平常所使用的debug口就是console。

  • uart_port

//描述一个UART端口
struct uart_port {spinlock_t    lock;      /* port lock */unsigned long    iobase;      /* in/out[bwl] */unsigned char __iomem  *membase;    /* read/write[bwl] */unsigned int    (*serial_in)(struct uart_port *, int);void      (*serial_out)(struct uart_port *, int, int);void      (*set_termios)(struct uart_port *,struct ktermios *new,struct ktermios *old);void      (*set_ldisc)(struct uart_port *,struct ktermios *);unsigned int    (*get_mctrl)(struct uart_port *);void      (*set_mctrl)(struct uart_port *, unsigned int);unsigned int    (*get_divisor)(struct uart_port *,unsigned int baud,unsigned int *frac);void      (*set_divisor)(struct uart_port *,unsigned int baud,unsigned int quot,unsigned int quot_frac);int      (*startup)(struct uart_port *port);void      (*shutdown)(struct uart_port *port);void      (*throttle)(struct uart_port *port);void      (*unthrottle)(struct uart_port *port);//中断处理int      (*handle_irq)(struct uart_port *);void      (*pm)(struct uart_port *, unsigned int state,unsigned int old); //电源管理void      (*handle_break)(struct uart_port *);//485配置int      (*rs485_config)(struct uart_port *,struct serial_rs485 *rs485);int      (*iso7816_config)(struct uart_port *,struct serial_iso7816 *iso7816);unsigned int    irq;      /* 中断号 */unsigned long    irqflags;    /* 中断标志  */unsigned int    uartclk;    /* 串口时钟 */unsigned int    fifosize;    /* tx fifo size */unsigned char    x_char;      /* xon/xoff char */unsigned char    regshift;    /* reg offset shift */unsigned char    iotype;      /* io access style */unsigned char    quirks;      /* internal quirks *///省略宏定义....unsigned int    read_status_mask;  /* driver specific */unsigned int    ignore_status_mask;  /* driver specific */struct uart_state  *state;      /* pointer to parent state */struct uart_icount  icount;      /* statistics */struct console    *cons;      /* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)unsigned long    sysrq;      /* sysrq timeout */
#endif/* flags must be updated while holding port mutex */upf_t      flags;
//省略宏定义....upstat_t    status;
//省略宏定义....int      hw_stopped;    /* sw-assisted CTS flow state */unsigned int    mctrl;      /* current modem ctrl settings */unsigned int    timeout;    /* character-based timeout */unsigned int    type;      /* port type */const struct uart_ops  *ops;     //串口操作函数unsigned int    custom_divisor;unsigned int    line;      /* port index */unsigned int    minor;resource_size_t    mapbase;    /* for ioremap */resource_size_t    mapsize;struct device    *dev;      /* parent device */unsigned char    hub6;      /* this should be in the 8250 driver */unsigned char    suspended;unsigned char    unused[2];const char    *name;      /* port name */struct attribute_group  *attr_group;    /* port specific attributes */const struct attribute_group **tty_groups;  /* all attributes (serial core use only) */struct serial_rs485     rs485;struct serial_iso7816   iso7816;void      *private_data;    /* generic platform data pointer */
};

uart_port用于描述一个UART端口的I/O端口或I/O内存地址、FIFO大小、端口类型等信息。这个结构体参数很多,还有很多对串口进行配置的函数。

  • uart_ops

//物理硬件的所有操作
struct uart_ops {//一些操作函数unsigned int  (*tx_empty)(struct uart_port *);//判断发送FIFO是否为空void    (*set_mctrl)(struct uart_port *, unsigned int mctrl); //设置控制信息unsigned int  (*get_mctrl)(struct uart_port *); //获取当前控制信息void    (*stop_tx)(struct uart_port *); //停止txvoid    (*start_tx)(struct uart_port *);//启动txvoid    (*throttle)(struct uart_port *);//通知串口驱动,线路规程输入缓冲区接近满了void    (*unthrottle)(struct uart_port *);//通知串口驱动可以将字符发送到线路规程输入缓冲区void    (*send_xchar)(struct uart_port *, char ch); //传输高优先级字符,即使端口已停止。void    (*stop_rx)(struct uart_port *); //停止Rxvoid    (*enable_ms)(struct uart_port *); //使能modem状态中断void    (*break_ctl)(struct uart_port *, int ctl); //控制中断信号的传输int    (*startup)(struct uart_port *); //启动串口void    (*shutdown)(struct uart_port *); //关闭串口void    (*flush_buffer)(struct uart_port *); //刷新写buffer,复位DMAvoid    (*set_termios)(struct uart_port *, struct ktermios *new,struct ktermios *old); //改变串口参数,包括字长,奇偶校验,停止位。void    (*set_ldisc)(struct uart_port *, struct ktermios *); //通知线路规程改变void    (*pm)(struct uart_port *, unsigned int state,unsigned int oldstate); //电源管理//返回一个描述串口类型的字符串const char  *(*type)(struct uart_port *);//释放IO和内存资源void    (*release_port)(struct uart_port *);//申请IO和内存资源int    (*request_port)(struct uart_port *);//配置串口void    (*config_port)(struct uart_port *, int);int    (*verify_port)(struct uart_port *, struct serial_struct *);int    (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLLint    (*poll_init)(struct uart_port *);void    (*poll_put_char)(struct uart_port *, unsigned char);int    (*poll_get_char)(struct uart_port *);
#endif
};
  • uart_driver是对tty_driver的封装,uart_driver和platform_driver还是有区别的,因为它并没有probe回调函数。它主要是一些字符设备的信息

  • uart_port用来描述具体的串口,主要是一些串口参数

  • uart_ops就是一些串口的操作函数,和字符设备中的file_operations差不多。

API函数

//注册/注销uart_driver到串口核心层
int uart_register_driver(struct uart_driver *drv)
void uart_unregister_driver(struct uart_driver *drv)//关联具体串口和驱动
int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
//移除串口和驱动的管理
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)

我们使用到的接口函数很少,所以其实蛮简单的,Linux封装完之后就是填充结构体,然后调用接口注册一下。

总结

首先我们要清楚,在底层,Uart驱动是为每个port都分配了缓存空间的。所以应用层读取的都是缓存空间中的。然后uart_driver不能和platform_driver混淆。后面我们分析实例时会发现Uart的驱动是由platform_driver来回调probe的。之前说过,控制器都是使用platform_driver, 串口对于芯片而言,也是一个控制器。

分析一大堆代码是不是看着很累,所以千万别全部看,挑重点看,理清思路即可。

更多好文,关注公众号

Linux驱动分析之Uart驱动架构相关推荐

  1. Linux spi驱动分析----SPI设备驱动(W25Q32BV)

    转载地址:http://blog.chinaunix.net/uid-25445243-id-4026974.html 一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它 ...

  2. Linux RS232/485/GPS 驱动实验(2)-UART 驱动分析

    1.UART 的 platform 驱动框架 打开 imx6ull.dtsi 文件,找到 UART3 对应的子节点,子节点内容如下所示: 1 uart3: serial@021ec000 { 2 co ...

  3. usb serial port 驱动_tty初探 — uart驱动框架分析

    写在前面: 我们没有讲UART驱动,不过我们认为,只要系统学习了第2期,应该具备分析UART驱动的能力,小编做答疑几年以来,陆陆续续有不少人问到UART驱动怎么写,所以今天就分享一篇深度长文(1700 ...

  4. linux 网卡驱动分析,LINUX_网卡驱动分析

    LINUX_网卡驱动分析 (36页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.9 积分 Linux DM9000网卡驱动程序完全分析说明仁 本文分 ...

  5. linux下camera驱动分析_LINUX设备驱动模型分析之三 驱动模块相关(DRIVER)接口分析...

    本系列前几篇文章链接如下: <LINUX设备驱动模型分析之一 总体概念说明> <LINUX设备驱动模型分析之二 总线(BUS)接口分析> 上一章我们分析了bus-driver- ...

  6. linux pl320 mbox控制器驱动分析-(3) pl320驱动代码分析

    linux pl320 mbox控制器驱动分析-(3)pl320驱动代码分析 1 pl320 mbox控制器宏定义 2 初始化接口 3 ipc_handler mbox中断处理函数 4 数据的收发 4 ...

  7. android 触摸屏驱动分析,Android 触摸屏驱动代码分析(ADC 类型触摸屏 CPU:s3c

    Android 2.1 farsight version for s5pc100 File Name: s3c-ts.c 1           简介 1.1          本例基于s5pc100 ...

  8. 触摸屏驱动分析: (本机驱动)

    触摸屏驱动为本机驱动,由微软提供有通用层 MDD,我们只需要编写PDD层就可以了.触摸屏驱动由GWES 加载,GWES 通过MDD层的DDI设备驱动程序接口函数(Device Driver Inter ...

  9. linux设备模型之tty驱动架构分析,linux设备模型之uart驱动架构分析

    五: uart_add_one_port()操作本文引用地址:http://www.eepw.com.cn/article/201610/305916.htm 在前面提到.在对uart设备文件过程中. ...

最新文章

  1. 手绘线条一直画不直_我学素描,线条画不直怎么办啊?
  2. [hypervisor]-ARMV8的hypervisor技术介绍–InProgress
  3. 编程开发使用的软件大全
  4. 二面蚂蚁金服(交叉面),已拿offer,Java岗定级阿里P6
  5. vim匹配特定的行并删除它
  6. 看从小自带BUFF的他,如何用代码降低万物互联的门槛
  7. html的定位属性,CSS之定位属性
  8. catkin_make:Project ‘cv_bridge‘ specifies ‘/usr/include/opencv‘ as an include dir, which is not fo
  9. Kotlin 区间的一些小注意
  10. 有关学习Android资料的一些网站
  11. C语言函数库之字符串连接函数(string.h)
  12. 第三方Banner制作轮播图的具体方法
  13. 电脑重装win10系统bios不会设置?用这种方法可以轻松重装系统
  14. 基于Java毕业设计服务管理系统源码+系统+mysql+lw文档+部署软件
  15. 跨模态行人重识别:Deep Learning for Person Re-identification:A Survey and Outlook(行人重识别综述)
  16. 030 | 广西趣海有限责任公司创业计划书 | 大学生创新训练项目申请书 | 极致技术工厂
  17. 《阿凡达》的元宇宙帝国多久抵达现实?
  18. Cris 的Python笔记(十一):面向对象三大特征之多态
  19. 教你删除鼠标右键菜单,清理“新建”菜单的方法!
  20. 筑泰防务受邀参加公安无线通信与移动警务技术应用研讨会

热门文章

  1. [易飞]没做采购变更单,采购单被指定结束了?
  2. 智慧工地安全帽识别检测算法 yolov5
  3. [CNN]|CNN与Transformer区别
  4. 读曾仕强的《易经的奥秘》简摘
  5. 上最全!无线路由器常见问题大集合
  6. ScanNet数据集讲解与点云数据下载
  7. python可以写什么视觉特效_星球大战视觉特效背后的功臣——Python
  8. 如何设计一个优雅健壮的Android WebView?(上)
  9. EIS防抖-电子防抖技术
  10. [天龙/汉威]可变信息标志通信协议-向可变信息标志上载文件(JAVA版)