uart子系统

uart无论在ARM,Android/Linux,还是MCU裸机中都应用非常广泛,TTL/RS232/RS485都是uart实现,只是电平差别.
uart以其良好的兼容性/低成本/传输距离等优点,广泛应用.

本文记录自己对uart的一些理解.

硬件拓扑:
SOC都封装了一个uart控制器,一个uart控制器(以8250为例)引出多个uart口.一个uart口接一个具体的硬件设备.
同时SPI设备/USB设备/i2c设备,也可以成为uart控制器,分出uart口.

uart是tty 子系统中三大块之一(终端terminal,控制台console,串口uart).

tty框架如下,
在这里插入图片描述

对于普通串口,应用层也是以系统调用open(/dev/ttySx,…)/write/read方式直接操作ttySx方式
调用过程参考https://blog.csdn.net/Jalyn_Fang/article/details/55798671

因此,用户控制主要还是通过设备文件同tty_core交互,tty_core跟进用户空间操作的类型选择合适的线路规定或者直接与serial core交互(例如ioctl会直接交给serial_core,read/write会交给线路规程).
线路规程,可以理解 为应用程序和设备驱动之间的一个适配层,主要为了描述这个操作串口的线程的输入输出规范,主要用来进行输入/输出数据的预处理.处理之后,简单理解就是将输入的字符转化成一行一行的数据,将数据交给serial_core,最后serial_core会调用底层的操作.主要实现文件n_tty.c

为了解uart,必须了解它的更高以及框架tty框架.
TTY是各类终端设备的简称,为了简化TTY的使用,Linux kernel抽象出了tty framework,对上,以字符设备(tty_io.c)的形式(tty_core),为用户提供标准应用api,对下,提供编写终端程序(如serial_core)的统一框架.

tty framework 框架如下
在这里插入图片描述

tty框架以及其子设备,由于出现的时间比较早,与经典的设备驱动模型并不非常符合,其弱化了device的概念,而增强了driver的结构和功能.这一点要注意.

有对tty framework的基本了解,我们再来看看Linux对uart的处理.
以RK3288-Android7.1SDK为例,Linux kernel版本4.4.143

RK3288 其硬件uart控制器,采用的是synopsys DesignWare 8250 IP.
kernel的分析从8250_core.c开始.

Linux kernel将具体的串口硬件抽象为uart_port.某些具体的SOC,也会在这个基础上重新封装一层.

8250作为虚拟的plaform_device.没有在dts中声明,8250_core.c的module_init中以显示指定serial8250字段的形式调用platform_device_alloc申请platform_device.然后直接显示注册platform_device_add().然后再注册驱动platform_driver_register,进而probe起作用,完成后续的任务.

Linux driver将uart控制8250抽象为struct uart_8250_port.该结构里面包含struct uart_port;这个变量.

serial8250_init中,
1.显式对8250下的5个uart_port分别初始化,指定uart_ops回调函数集.
2.调用uart_register_driver,注册8250 uart_driver.在这个uart_register_driver里面,会定义tty_driver,作为uart_driver的一个成员.并初始化tty_operation,这个tty_operation直接和tty framework最顶层的字符设备接口相联系,被其直接调用.
再一个,会初始化每一个uart_port的uart_state(uart_state对应与串口接的具体的硬件设备),uart_state有一个tty_port,对应于/dev/ttySx,然后会为这个tty_port申请buf缓冲区.然后通过tty_register_driver(),将申请的tty_driver注册到tty_core

对于uart,有tty_operation,uart_ops两个函数集非常重要,tty_operation负责实现tty字符设备api的具体实现,uart_ops负责本soc关于uart寄存器级别的实现.

但是,8250_core.c里面serial8250_init相关的uart_port还是一个虚拟的概念,还没有与具体的dts中的uart设备关联起来的,那么这个是怎么关联的呢?
先看uart再dts中的定义,

uart0: serial@ff180000 {
	compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
	reg = <0x0 0xff180000 0x0 0x100>;
	interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
	reg-shift = <2>;
	reg-io-width = <4>;
	clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
	clock-names = "baudclk", "apb_pclk";
	pinctrl-names = "default";
	pinctrl-0 = <&uart0_xfer>;
	status = "disabled";
};

通过compatible字段关键字查找,可以找到其对于的driver是8250_dw.c
在该驱动的probe里面,显示申请了uart_port,然后解析dts,使用从dts解析的参数初始化uart_port成员.然后调用serial8250_register_8250_port注册该uart_port.
这个所谓注册,就是从serial8250_ports这个port里面,找到一个和当前uart_port匹配或者空虚的port,完成虚拟uart_port和硬件实际uart_port的关联,进而使得字符设备/dev/ttySx具有了灵魂和肉体,
下一步工作,就是实现串口start_up,serail_in,serial_out相关与具体硬件相关的功能实现.

对于uart,或者整个tty,已经非常的完善,需要修改的东西比较少,我们只需要了解其过程,能否理解应用层的操作逻辑,能应付基本的任务.

由于时间和能力关系,暂分析到此.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九月天-深圳专业软硬件开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值