ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

总线仲裁与定时协议:从CAN到AHB,搞懂共享总线的路权与时序

总线仲裁与定时协议:从CAN到AHB,搞懂共享总线的路权与时序 最近调试一套多节点CAN总线设备的时候我又一次被总线拥堵虐了一遍三块控制板挂在同一条双绞线上运行一段时间后其中一块偶发性报错波形上看有明显的位填充违规但单独测每块板子都正常。这种问题最折磨人——不是板子坏了而是共享总线的秩序出了问题。总线仲裁和定时协议这两个词听起来像教科书里的概念实际上就是解决这类问题的关键。这篇文章我打算把总线仲裁和定时协议这两件事彻底讲透为什么共享总线必须要有仲裁主流总线CAN、I2C、AMBA AHB/APB各自用什么机制分配路权定时协议又是怎么约束每个节点什么时候说话、说多久的。无论你是做嵌入式、汽车电子还是写驱动、调SoC集成理解这套底层逻辑排查起总线问题会顺手很多。1. 共享总线的拥堵从何而来多主设备共用一条通道的本质矛盾1.1 所谓的总线仲裁到底在仲裁什么很多人一听总线仲裁就想到CPU和内存之间的地址总线觉得那是芯片设计人员才需要关心的事。实际上只要两个或两个以上的设备共用一条物理通道传输数据仲裁就不可避免。总线仲裁的本质是解决同一时刻谁能占用共享媒介的决策问题。以CAN总线为例总线上挂的ECU、传感器、执行器都是节点它们地位上是对等的谁都没资格命令别人你先别发。如果不做任何仲裁两个节点同时向总线发送电平电气上就会直接冲突接收端读到的电平是乱的数据全废。再说I2C总线它支持多主机模式两个主机可以在同一时刻启动传输。如果没有仲裁机制SCL和SDA两根线上的数据会交叠从机收到的一定是垃圾数据。所以I2C在物理层和协议层都设计了仲裁——后面我会展开讲。AMBA AHB总线更典型一个SoC里可能有CPU、DMA控制器、以太网MAC等多个主设备它们都想访问内存或外设。AHB的做法是引入一个中央仲裁器Arbiter所有主设备想用总线必须先向仲裁器发起请求仲裁器根据优先级或轮询策略把总线使用权授予其中一个主设备。这三类总线的仲裁思路各不相同但核心矛盾是同一个共享媒介的容量有限多设备并发需求无限必须有一个可预测、可实现的规则来决定谁先用。1.2 电气层共享开漏、推挽与显性/隐性电平的物理规则仲裁不仅仅是协议层的事物理层早就把规则定死了。不同总线在电气实现上天然决定了它能采用什么仲裁方式。推挽输出Push-Pull的方式输出级要么拉高要么拉低没有第三种空闲状态。SPI就是典型的推挽总线所以SPI根本不支持多主机仲裁——它通过片选信号CS把总线物理隔离给某个主机谁拉低CS谁就独占这条总线。这是最原始也是最好理解的仲裁用一根专用线当锁其他主机想用也没办法。开漏输出Open-Drain的I2C则是另一套逻辑。开漏结构只能主动拉低不能主动拉高释放引脚后靠上拉电阻把电平拉高。这个特性决定了只要有一个设备拉低这条线就是低电平所有设备都释放线才是高电平。I2C总线就是利用线与Wired-AND特性做仲裁的——仲裁时谁先输出低电平谁就主导总线另一个主机发现电平与自己预期不符就自动退出。CAN总线的物理层更讲究它定义了显性Dominant和隐性Recessive两种电平。显性电平对应逻辑0隐性电平对应逻辑1显性电平和隐性电平同时出现时显性优先。CAN收发器的驱动器是推挽和开漏的混合体显性位靠主动驱动差分电压产生隐性位靠释放总线让终端电阻和偏置电路把差分电压拉到0附近。这套显性优先的物理规则是CAN逐位仲裁能够成立的基础。2. 几种主流仲裁机制的博弈逻辑CAN逐位仲裁、I2C开漏仲裁、AHB中央仲裁2.1 CAN总线的非破坏性逐位仲裁原理CAN总线用的是CSMA/CR载波监听、逐位冲突解析机制和以太网的CSMA/CD冲突检测有本质区别。以太网检测到冲突后会停止发送、随机退避再重传而CAN在仲裁过程中获胜的节点毫发无损地继续发送失败的节点自动转为接收状态不发任何破坏性信号——这就是非破坏性三个字的由来。具体流程是这样的节点在发送帧前先监听总线检测到总线空闲后开始发送帧起始位SOF。从SOF之后的仲裁场开始每个节点逐位发送自己的标识符ID同时每发送一位就回读总线电平。由于显性位0会覆盖隐性位1如果某个节点发送隐性位1却读到总线上是显性位0就说明有其他节点同时在发送并且对方的标识符在这一位上是0优先级更高。这个节点立即停止发送转入接收状态等待总线空闲后再次尝试。这套机制的精妙之处在于仲裁失败不会导致任何数据被破坏已经发出的位仍然有效。所以CAN总线上ID越小优先级越高ID为0x001的帧永远能抢过ID为0x7FF的帧。实际工程里很多新手不理解ID越小优先级越高这一条为了把某条报文做成高优先级反而把ID设得很小结果整条总线的实时性全被打乱。真正合理的做法是把对时延最敏感的报文如转向控制、刹车指令分配最小的ID把周期性的普通状态报文分配较大的ID绝对不要把诊断类报文放在低ID区间。2.2 I2C总线的沈默退让机制I2C的多主机仲裁经常被忽视因为大部分产品只用一个主机。但只要涉及双主机热备份、主从切换这种场景I2C仲裁就非常关键。I2C仲裁发生在SCL线为高电平时主机在SDA线上发送数据位。因为I2C是开漏结构加线与逻辑如果主机A想发送高电平释放SDA主机B想发送低电平拉低SDA总线上的实际电平就是低。主机A在发送高电平时回读SDA发现读到的不是高而是低就知道自己仲裁失败了立刻放弃SDA控制权。这里有个隐藏细节I2C仲裁不只发生在数据位地址位、应答位都会参与仲裁。如果两个主机要访问不同的从机地址不同在地址阶段就能分出胜负如果地址相同数据位接着仲裁直到一方发出不同电平。仲裁失败的节点必须在当前传输结束后才能重新尝试不能立刻抢占总线。I2C仲裁还有一条容易踩坑的规则SCL线是低电平同步的。多个主机在总线空闲时同时发起START它们的SCL线会被拉低每个主机都会在SCL低电平时把自己的时钟拉低然后等待SCL释放。由于所有主机共享一条SCL实际上所有设备会同步到最慢的那个节点的时钟——这是I2C规范里慢速设备通过拉低SCL延长传输周期机制能够工作的根本原因。2.3 AHB/APB总线中的固定优先级与轮询仲裁AMBA总线是另一套完全不同的仲裁哲学。AHBAdvanced High-performance Bus专门为高性能、高时钟频率的系统设计它不像CAN和I2C那样在电气层做分布式的逐位仲裁而是引入了中央仲裁器。每个AHB主设备都有一对信号HBUSREQ总线请求和HGRANT总线授权。主设备需要访问总线时拉高HBUSREQ仲裁器根据设定好的优先级策略在一个时钟周期后通过HGRANT信号把总线授权给某个主设备。仲裁器还可以通过HLOCK信号让某个主设备锁定总线完成多拍不被打断的burst传输。AHB仲裁策略主要分固定优先级和轮询两种。固定优先级实现简单适合有明确主从关系的系统——比如CPU永远优先于DMA轮询则保证每个主设备都能轮流获得总线使用权避免低优先级设备饿死。实际SoC里常常是混合策略某一个高优先级主设备始终优先其余主设备按轮询方式共享剩余带宽。APBAdvanced Peripheral Bus则是AMBA家族里的轻量级选手它只有唯一的主设备——通常是AHB到APB的桥接器。APB不需要仲裁它把全部精力放在状态机时序上IDLE、SETUP、ACCESS三个状态严格规定了读写访问的时序。PSEL信号选通从设备PENABLE信号作为访问阶段的使能PREADY信号则是从设备用来插入等待周期的握手信号。APB没有仲裁不代表APB不存在冲突问题。APB桥接器作为AHB的从设备它本身要参与AHB仲裁如果AHB总线上同时有CPU和DMA访问APB区域CPU要等待DMA的burst传输结束才能通过桥接器访问APB外设这个延迟在实时系统里必须考虑。3. 定时协议仲裁之外的红绿灯规则3.1 CAN位定时同步段、传播段、相位缓冲段与采样点仲裁决定了谁先走定时协议则决定了走多远算一步。CAN总线的定时协议比大多数人想象得要精细得多。CAN总线上的每一位Bit Time不是简单的一个时钟周期而是由四个段组成同步段Sync_Seg用于同步总线上的各个节点长度固定为1个时间量子Tq。传播段Prop_Seg用于补偿物理传输延迟包括收发器延迟、总线传播延迟、接收节点输入比较器延迟。相位缓冲段1Phase_Seg1用于补偿边沿相位误差可以在重同步时被延长。相位缓冲段2Phase_Seg2用于补偿边沿相位误差可以在重同步时被缩短。采样点Sample Point位于Phase_Seg1和Phase_Seg2之间节点在这个时刻读取总线电平判定当前位是0还是1。采样点的位置非常关键。采样点太早后面还有大量数据位在物理线上传播没有稳定下来容易采错采样点太晚留给相位缓冲段2的余量不足重同步能力变差。业界经验一般认为采样点应该在75%左右汽车电子常用的是75%到80%。比如一个位时间由20个Tq组成采样点设在75%就是第15个Tq处采样。很多人在配置CAN控制器时只关注波特率而不关注采样点用默认值直接跑起来。低速短距离通信125kbps、几米线缆通常没问题一旦通信距离拉长到几十米或波特率提高到500kbps以上采样点配置不合理就会产生偶发性错误帧。我之前调试过一条50米长的CAN总线波特率500kbps接收节点采样点默认60%总线长度增加后频繁丢失报文把采样点调整到75%之后问题立刻消失。3.2 握手协议SPI相位极性、I2C ACK时序、AHB HREADY与APB PREADY定时协议在整个总线语境下还包括各种握手信号的时序关系。SPI虽然不是共享多主总线但它的CPOL时钟极性和CPHA时钟相位配置是定时协议最直观的教科书案例。CPOL决定空闲时SCK是高还是低CPHA决定数据在SCK的哪个边沿被采样。主机和从机只要有一边配置不一致收发的数据就是乱的。SPI通信最让人头疼的不是时序复杂而是电平对、协议对但CPHA配反这种问题示波器上看到的波形看起来完美实际数据全是错的。I2C的ACK时序同样属于定时协议。从机在接收完第8个数据位后必须在第9个时钟周期内拉低SDA作为应答。如果从机忙不过来正在处理EEPROM写入或内部状态机没跟上它可以释放SDA给NACK主机收到NACK后停止当前传输。这个时序窗口是固定的从机不能延迟应答只能在发送NACK后让主机决定是否重发。AHB的HREADY信号是另一个典型的握手定时协议。HREADY拉低时表示从设备还没准备好需要插入等待周期主设备的地址、控制信号和数据信号必须保持稳定直到HREADY拉高。这个过程打破了一拍完成传输的默认假设真实系统的时序分析必须考虑这种可变延迟。APB的PREADY和HREADY功能类似但从设备只能在SETUP到ACCESS状态转换时通过PREADY控制访问周期。很多芯片数据手册给的是最小PREADY建立时间这类参数实际调试时如果寄存器配置里把APB从设备的等待周期设得过短读操作就会读到未稳定的数据。3.3 时序违规的类型与结果建立时间、保持时间和总线正时总线上的数据能不能被正确采样归根到底取决于采样边沿和数据变化沿之间的时间关系。建立时间Setup Time要求数据在采样边沿到来之前提前稳定一定时间保持时间Hold Time要求数据在采样边沿之后继续保持一定时间。这个逻辑在芯片内部和总线协议里是通用的。AHB总线上从设备对地址信号就有建立时间要求地址必须在HCLK上升沿之前稳定否则从设备可能采到不稳定的地址。FPGA设计里如果综合后在总线上出现源寄存器到目的寄存器的时序违规表现出来就是偶发性的数据错乱而且故障位置随温度电压漂移非常难排查。CAN总线的总线正时概念也属于定时协议的范畴。总线正时指的是各个节点之间的时钟同步精度。CAN规定两个节点间的时钟误差必须在特定范围内否则即使波特率设置相同位时序也会逐渐漂移最终导致采样点落在错误的位区间。标准CAN要求时钟容差大约在±0.5%以内所以工业上普遍使用带晶振的CAN控制器而不是RC振荡器——RC振荡器温漂太大长时间运行时位同步迟早会崩溃。4. 从现象反推问题调试仲裁冲突与定时违规的实战经验4.1 用示波器判读CAN总线波形如何通过波形判断通信质量很多工程师排查CAN总线问题第一步就是拿示波器量CAN_H和CAN_L之间的差分电压。CAN显性位时CAN_H约3.5VCAN_L约1.5V差分电压约2V隐性位时CAN_H和CAN_L都约2.5V差分电压约0V。如果示波器上看到的波形根本不是这个形态先不要急着分析协议大概率是物理层出了问题。常见的波形异常有几种差分电压摆幅偏小比如只有1V很可能是终端电阻阻值不对或者总线节点太多等效负载过大。隐性电平不为2.5V整体上偏或下偏可能是收发器故障或偏置网络出了问题。波形边沿有明显的振铃或台阶通常和线缆阻抗不匹配有关终端电阻漏接是最常见的原因。显性位和隐性位的切换速率非常慢可能是线缆过长、分布电容过大或者收发器的压摆率设置太低。需要注意的是示波器要测量CAN_H和CAN_L的差分波形最好用差分探头或至少用两个通道做数学减。直接用单端探头测量CAN_H对地电压看到的噪声和共模干扰会误导判断。带宽足够高至少100MHz的示波器才能捕捉到位边沿的真实形态。4.2 现场案例多节点CAN总线一台设备掉线怎样锁定故障节点我调试AGV调度系统时遇到过这样一个案例5台AGV的控制器挂在一条CAN总线上运行几个小时后其中一台设备开始周期性掉线掉线几秒后自己恢复过一会又掉线。排查过程是这样走的第一步用示波器盯住总线空闲时的波形。发现总线上偶尔出现幅值异常的短脉冲看起来像某个节点在发送但数据不完整。这通常是节点发送了错误帧或仲裁失败的残留信号。第二步逐个节点隔离。把可疑节点从总线上断开跑一整天不再掉线接回去几个小时后又复现。锁定是这台设备的问题。第三步仔细检查这台设备的CAN控制器配置。发现它的波特率计算有微小偏差标称500kbps实际测量大概499.6kbps。单独和上位机通信时误差在容差范围内协议栈可以重同步不影响通信。但5台设备共享总线时其他节点的精确定时器和这个节点反复做重同步最终某些位的采样点落在了错误位置触发错误帧。修正波特率分频器配置后问题彻底消失。这个案例的教训是多节点共享总线时任何一个节点的时钟精度不达标都会以概率性掉线的形式表现出来和它自己的负载大小往往无关。4.3 逻辑分析仪与交叉握手调试APB/AHB时序的实操要点AMBA总线时序调试景深分析仪远远不够用逻辑分析仪才是主力。抓信号的时候有几个要点至少同时抓HCLK、HREADY、HWRITE、HSEL、地址线、数据线。只抓地址和数据不抓握手信号定位不了问题。APB调试要抓PSEL、PENABLE、PREADY。如果发现从设备一直不拉高PREADY大概率是从设备时钟没供上或者从设备处于复位状态。注意触发条件设置可以使用HREADY的下降沿作为触发条件快速找到总线卡死的现场。我遇到过最典型的APB故障是这么回事一个外设模块挂在APB总线上访问它的某个寄存器时系统偶发挂起。逻辑分析仪抓到PENABLE拉高后PREADY一直为低。这是因为APB从设备的PCLK没使能从设备完全不知道有人在访问它根本不会响应。软件上看起来是访问寄存器卡死实际上是时钟门控策略把外设时钟关了APB握手自然无法完成。这种问题如果不去看握手波形光靠读代码可能要花很长时间才能想到。5. 系统级调度视角从总线仲裁到任务调度与集群调度的同构关系5.1 总线仲裁机制对操作系统调度的启发总线仲裁并不是只在硬件层面存在。操作系统里的任务调度本质上也是多个执行单元竞争一个CPU核心的仲裁问题。CAN总线的优先级仲裁和RTOS里基于优先级的抢占式调度非常像。CAN的低ID号对应高优先级RTOS里的小数值优先级对应高优先级两者都是数值越小越优先。CAN仲裁失败后自动重发对应RTOS里高优先级任务就绪后抢占低优先级任务的CPU使用权。核心思想一致谁更紧急谁先占用共享资源。APB的唯一主设备模型对应到软件上就是单核单片机的前后台大循环架构——没有抢占永远只有一个主循环在跑。AHB的中央仲裁器则对应多核处理器里的中断控制器或调度器所有核要访问共享缓存或外设必须通过仲裁机制排队。5.2 从总线仲裁到集群调度的映射更高一层看集群调度和分布式任务分配也在解决同样的问题多个计算节点共享网络带宽、存储资源、任务队列需要调度器统一分配。集群调度可以借鉴总线仲裁的思路优先级策略紧急任务实时推理、故障告警像CAN的低ID帧一样抢占资源轮询策略批量任务像AHB的轮询仲裁一样轮流使用计算节点避免饥饿锁机制分布式锁和AHB的HLOCK锁定总线是同一个概念防止并发修改共享数据。比如之前我参与过一个边缘计算的调度模块设计在一个GPU节点上同时跑实时推理和离线视频分析任务。如果只设固定优先级离线任务经常饿死只做轮询实时推理的延迟就超出指标。最后参考AHB混合策略实时推理用最高优先级分析任务在剩余时间片里轮询。这个方案和SoC里的总线仲裁器设计如出一辙。5.3 熟悉仲裁机制之后看问题会更通透总线仲裁和定时协议不是一个记住结论就够的知识点。仲裁的几种典型策略——逐位竞争、开漏让权、中央裁决、轮询——其实覆盖了并发场景下资源分配的主要模式。理解了CAN的逐位仲裁再看I2C的开漏仲裁再看AHB的中央仲裁器你会发现它们的演进脉络是很清晰的从物理层的自然约束到协议层的规则博弈再到系统级的统一调度。定时协议也一样。采样点、握手信号、建立保持时间这些概念都是为了让多方通信在面对不可预知的延迟和偏差时依然能稳定工作。读懂定时协议本质上就是读懂如何在时间维度上保证确定性。调试总线问题多年我越来越觉得遇到仲裁和定时相关的故障不要急着改代码或换器件先用示波器和逻辑分析仪把物理层、协议层、时间层的真相全部抓出来再动手。波形的每一个毛刺、握手信号的每一拍延迟都在告诉你总线正在经历什么。看得懂电平和时序总线就会从一团乱麻变成一目了然的地图。
返回列表