本文分享电子系统中信号波形的动图,有助于帮助我们理解传输的机理。

1. SPI传输

SPI

图1 SPI 数据传输

PCIe Gen5 Signal Integrity Test

PCIe总线是服务器系统里最重要的总线,经过PCIe信号的互联,CPU得以与各种外设部件进行通信。在这些年,追赶业界带宽需求的PCIE和PCIe 6.0规范及之后的技术展望等文章里,我们即回顾了PCIe信号发展的历史,又重点探讨了最前沿的PCIe 6.0规范的性能指标。PCIe 6.0 Base Specification目前刚刚发布Draft 0.5版本,预计要到2021年才会正式发布;PCIe 6.0 CEM Specification的制定还未启动,PCI-SIG组织正在酝酿之中。与此同时,随着Intel支持PCIe 4.0的Ice Lake Xeon-SP CPU即将在今年底发布,再加上支持PCIe 4.0的AMD EPYC CPU和一众ARM CPU的逐渐出货,PCIe 4.0即将在2021年成为市场上的主流。在当下这个时间节点,广大服务器设计人员可能更应该关注会在2021-2022之间成为谈论热点的PCIe 5.0。

PCIe Gen5 Signal Integrity Test

PCIe 5.0的主要特性

PCIe 5.0 Base Specification已经在2019年5月正式发布,但与之配套的定义Add-in-Card设计和性能要求的PCIe 5.0 CEM Specification刚刚公布Draft 0.7版本,定义电气信号测试方法的PCI Express 5.0 Architecture PHY Test Specification还未开始制定。因此,PCIe 5.0当前的重点已经从信号设计转向了信号测试方法的制定。

硬盘是大家都很熟悉的设备,一路走来,从HDD到SSD,从SATA到NVMe,作为NVMe SSD的前端接口,PCIe再次进入我们的视野。作为x86体系关键的一环,PCIe标准历经PCI、PCI-X和PCIe,走过近30年时光。其中,Host发现与查找设备的方式却一脉沿袭。今天,我们就来聊聊PCIe设备在一个系统中是如何发现与访问的。

首先,我们来看一下在x86系统中,PCIe是什么样的一个体系架构。下图是一个PCIe的拓扑结构示例,PCIe协议支持256个Bus, 每条Bus最多支持32个Device,每个Device最多支持8个Function,所以由BDF(Bus,device,function)构成了每个PCIe设备节点的身份证号。

PCIe Bus

PCIe体系架构一般由root complex,switch,endpoint等类型的PCIe设备组成,在root complex和switch中通常会有一些embeded endpoint(这种设备对外不出PCIe接口)。这么多的设备,CPU启动后要怎么去找到并认出它们呢? Host对PCIe设备扫描是采用了深度优先算法,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。我们一般称这个过程为PCIe设备枚举。枚举过程中host通过配置读事物包来获取下游设备的信息,通过配置写事物包对下游设备进行设置。

第一步,PCI Host主桥扫描Bus 0上的设备(在一个处理器系统中,一般将Root complex中与Host Bridge相连接的PCI总线命名为PCI Bus 0),系统首先会忽略Bus 0上的embedded EP等不会挂接PCI桥的设备,主桥发现Bridge 1后,将Bridge1 下面的PCI Bus定为 Bus 1,系统将初始化Bridge 1的配置空间,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成0和1,以表明Bridge1 的上游总线是0,下游总线是1,由于还无法确定Bridge1下挂载设备的具体情况,系统先暂时将Subordinate Bus Number设为0xFF。

NVMe SPDK

长期以来,SATA、SAS盘统治着企业级存储,虽然前些年 SSD固态存储介质的出现对 AHCI协议类型的存储访问带来了一定性能提升,但与 CPU 的计算速度相比,只能是杯水车薪,并且 SSD 的性能也不能充分地得到发挥。传统存储技术也由于访问路径长、时延大和吞吐量低而越发不能满足 “大数据” 存储的需求,并且饱受诟病。

近几年推出的 NVMe 技术以 PCIe作为 SSD 的访问接口,极大地缩短了 I/O 的访问路径,同时 NVMe 的软件栈也以精简的调用关系进一步降低了数据访问的时延。可以说,NVMe 技术的出现和快速发展,是对存储技术领域的重大革新。由此 NVMe 存储的应用自然成了业内的发展趋势,各厂商也都积极投入NVMe存储的研发中来。

越来越多的分布式文件系统积极参与全闪阵营,通过横向扩展能力,对外提供块、对象、文件服务接口及一些增值特性服务,可以通过存储节点堆叠,获得容量和性能的同步提升。硬件上使用 RDMA、NVMe、NVDIMM等先进技术,提供高性能的硬件节点;同时采用软硬件一体化的设计达成高可靠性的目标。为了减少存储产品面临的传统共性问题,如频繁的系统调用和上下文切换、多次的数据拷贝、过高的协议栈开销、复杂的并发互斥等痛点问题,在用户态化实现的过程中,引入了 Intel 的 DPDK/SPDK作为关键基础技术来进行集成和开发。基于 DPDK 和 SPDK 的用户态实现前端NVMe-oF、FCP、iSCSI 块服务相关接口。

DPDK/SPDK 技术的引入,通过大页(Huge page)、轮询、分核、无锁化等机制减少了 CPU 上下文切换、并发互斥等带来的系统开销,提高了 I/O 的响应速度,带来了系统性能的提升,有效地解决了前端网络、后端网络和落盘等环节存在的性能瓶颈。同时 SPDK 提供的 BDEV 框架,定义了上层的访问接口,和下层存储设备的注册接口,向上可以支撑多种不同协议的Target,向下可以挂载多种不同的存储设备。BDEV 框架实现了对后端存储设备的统一抽象,可以和后端存储解耦,产品前后端可针对框架开发,减小模块耦合,进行独立的测试验证,提高了产品开发维护的效率。

Intel DPDK/SPDK 技术作为该产品设计的关键一环,与分布式架构融合应用,充分发挥全闪(NVMe)存储设备和 RDMA 传输通道的能力,提供了高性能的系统特性。当前产品开发的先期任务主要完成针对新技术的可行性分析、验证及高性能硬件节点的原型机开发:兼容业界主流厂商的 RDMA、FC卡,并基于 DPDK/SPDK 实现前端 NVMe-oF、FCP、iSCSI 块服务类型接口。当前的开发实现,验证了新一代全闪(NVMe)技术的高性能能力,为最终的分布式全闪(NVMe)存储产品的实现打下了坚实的基础。

看下面这张图,大家已经知道今天的主角是UART,我们通常说的串口,UART包含TTL电平和RS-232电平两种,嵌入式系统里面,单片机的串口一般都是TTL电平。

UART

今天的内容关于UART的帧格式,比较简单,玩过单片机的小伙伴应该都知道。

UART的英文全称是:Universal Asynchronous Receiver/Transmitter,意为通用异步收发传输器。

UART因为有两根线数据线TX和RX,可以以全双工的形式进行发送和接收数据,同一时刻,两条链路的发送器和接收器可以同时传输数据。

UART

区别于全双工的,还有另一种,是半双工,因为只有一根数据线,所以数据传输是这样。

UART

或者是下面这样,同一时刻,只有一条链路在传输数据。

UART

除了双工形式,还有一种是半工,只有发送器到接收器这一个链路。

UART

说完了UART的工作模式,下面进入主题——UART帧格式,也可以称之为UART协议,单片机与PC之间的通信,为了保证数据通信的可靠性,双方都必须遵从UART协议。

UART

UART数据帧格式

其中各位的含义如下:

  • 起始位:发送1位逻辑0(低电平),开始传输数据。
  • 数据位:可以是5~8位的数据,先发低位,再发高位,一般常见的就是8位(1个字节),其他的如7位的ASCII码。
  • 校验位:奇偶校验,将数据位加上校验位,1的位数为偶数(偶校验),1的位数4为奇数(奇校验)。
  • 停止位:停止位是数据传输结束的标志,可以是1/1.5/2位的逻辑1(高电平)。
  • 空闲位:空闲时数据线为高电平状态,代表无数据传输。

如果我们传输数据0X33(00110011),那么对应的波形就是如下这样,因为是LSB在前,所以8位数据依次是11001100

UART

发送0X33数据帧格式

如果再发其他数据,再依次循环这个过程即可。

UART是异步传输,以1个字符为传输单位,传输2个字符之间的时间间隔,比如传输0X33后再传输0X35,这两者时间间隔是未知的。

但是同一字符内相邻位间的时间间隔是确定的,比如0X33低两位的1和1之间的时间间隔是确定的,这涉及到UART传输速率的概念——波特率

波特率的单位是bps,全称是bit per second,意为每秒钟传输的bit数量。

波特率9600bps,代表每秒钟传输bit的数量为9600,那么传输1bit数据的时间就是1/9600=104us,波特率115200bps,代表传输1bit数据的时间是8us。

两个串口之间是如何发送和接受数据呢?

首先,UART1以9600波特率发送0X33,先在数据线上放1个104us脉宽的低电平(起始位),然后是连续2个104us脉宽的高电平(2bit逻辑1),依次类推。

其次,UART2以9600波特率接收0X33,通过数这些数据的脉宽,来确认数据。

为了确保数据传输的正确性,减少误差,一般UART1和UART2之间的波特率差别小于10%,一次最多只能传输1个字节(8bit),也有效减小了累计误差。