简介:计算机导论第二章“微型计算机系统的组成”配套教学课件,聚焦CPU、存储器、总线与输入/输出接口等核心内容,适合初学者系统理解硬件和软件整体构成。资源为1个PPT文件,共57张幻灯片,压缩包约923KB。页面按2.1概述、2.2中央处理器、2.3存储器、2.4总线与输入输出接口电路、2.5输入输出设备顺序组织,覆盖CPU字长与主频外频倍频、RAM/ROM分类、总线类型与AGP/PCI/IEEE1394、接口电路、进制转换、指令程序及软件系统等知识点。文档中包含大量硬件结构图、总线传输示意与字节单位换算表,图文结合,便于课堂演示或自学复习。目前已有57人学习浏览,可帮助梳理总线与设备间数据通路、内存与外存关系等易混淆内容,适合计算机专业入门者与备考计算机基础考试的学生参考。
1. 计算机导论里的“总线”,为什么值得单独讲 57 页
一台机器的数据传输,并不是从 CPU 到每个外设单独拉一条线。总线的本质,是一组被多个设备分时复用的公共线路,谁用、用多久、以什么节奏用,都由协议和仲裁逻辑说了算。它藏在 CPU 与内存之间、主板芯片组之间、传感器与主控之间,是计算机系统里最容易被忽略,却又最容易成为性能瓶颈的结构。如果把“计算机导论”中硬件章节做成课件,总线安排 50 多页并不夸张,因为一个话题要覆盖电信号、协议分层、仲裁机制、性能计算和系统拓扑。下文就顺着“总线”这条主线,把从概念到调试、从片上总线到工业总线的知识串起来,适合刚学完组成原理、准备做嵌入式或 Linux 驱动方向的同学,也能给系统工程师补上参数换算和调试经验的盲区。
2. 总线到底在传什么:数据线、地址线与仲裁机制
2.1 数据线、地址线与控制线:总线在物理上是什么
总线不是一根线。最早理解总线,最容易犯的错是把“总线”想象成一条粗电缆。实际上一组总线至少由三类信号组成:数据线、地址线、控制线。数据线的根数决定一次能并行传输多少 bit,也就是总线宽度;地址线根数决定总线上能挂的存储空间上限;控制线则负责任务的定义——读还是写、占用多久、是否结束。
比如早年 Intel 8086,16 位外部数据总线、20 位地址线,寻址上限是 2 的 20 次方即 1MB。这个数字在计算机导论里反复出现,它的意义不在于“1MB 很小”,而在于让你理解“地址线根数决定了系统能看到的地址空间”。放到现代处理器上仍然成立:64 位地址空间的虚拟地址上限虽然不被物理内存填满,但地址线宽度的概念没有变化。做嵌入式开发时,查看 datasheet 的 memory map,第一件事就是确认地址线宽度和片选信号,因为总线连接的是“地址经译码后选中设备”的逻辑,而不是简单的“把两个芯片的引脚接起来”。
2.2 总线宽度与寻址空间怎么算
总线宽度和寻址空间的换算有一个容易被忽略的细节:地址线 N 根能寻址 2 的 N 次方个地址单元,但每个地址单元不一定是 1 字节。有些 MCU 按 16 位字寻址,同样的地址线数量,寻址的字节数是 2 的 N 次方乘 2。设计系统时经常遇到“地址线不够用”的问题,常见做法是增加译码器,把高位地址线接到 74HC138 这类译码芯片上,扩展片选空间。
这里引入一个排错经验:如果读写外设时出现“地址镜像”,即访问一个地址导致多个设备同时响应,优先检查高位地址线是否悬空、译码器的使能端是否被错误拉低。地址镜像在总线上表现为“能读但回读值不稳定”,因为多个设备同时在驱动数据线。计算机导论的习题里经常提到地址译码计算,实际工作中遇到的总线问题反而多半出在译码器的时序使能上。
2.3 主设备、从设备与仲裁器:总线不是民主的
总线上每个设备角色不同。主设备可以发起读或写请求,例如 CPU、DMA 控制器、GPU;从设备只能响应请求,例如内存控制器、外设寄存器。一个总线系统通常至少有一个仲裁器,它的任务是在多个主设备同时请求总线时决定把使用权交给谁。
仲裁的常见做法有固定优先级、轮询和加权轮询三类,它们的特点见下表。
| 仲裁方式 | 决定权 | 优点 | 缺点 | 典型场景 |
|---|---|---|---|---|
| 固定优先级 | 优先级最高的请求先获权 | 实现简单、延迟可预测 | 低优先级请求可能长期得不到总线 | 简单 SoC 内存仲裁 |
| 轮询 | 按固定顺序轮流使用 | 公平,不会饿死 | 平均等待时间偏大 | AMBA APB 桥、老式 PCI |
| 加权轮询 | 按配置权重分配时隙 | 兼顾公平与高优先级 | 权重需按业务反复调 | 多核互连、网络交换芯片 |
2.3.1 固定优先级与轮询仲裁的取舍
固定优先级仲裁器在硬件上就是一组比较器,面积小、延迟低,适合主设备数量少且优先级明确的场合。它的明显问题是“饿死”:低优先级设备如果遇到持续的高优先级请求,会一直拿不到总线。轮询仲裁则用一个计数器在请求者之间循环,每个设备最坏等一轮,但由于所有请求都要排队,高优先级请求反而可能被低优先级拖慢。
实际 SoC 里常见做法是把仲裁做成可配置的:默认用固定优先级保证实时性,启动后用驱动写入寄存器切到轮询模式照顾吞吐。调试这类逻辑时,直接改寄存器里仲裁模式位,观察高优先级任务是否出现毛刺延迟,比在软件里数锁等待时间快得多。
2.3.2 为什么 RS232 不需要仲裁,而 CAN 必须仲裁
把这个问题想明白,总线才算是入门了。RS232 是点对点连接,发和收各用一根线,同一时刻只会两端通信,不存在第三方争抢,所以根本不需要仲裁。CAN 总线则不同,一条双绞线上可以挂几十个节点,任何一个节点都可以在总线空闲时主动发帧,如果没有仲裁,两个节点同时发帧就会冲突。
CAN 的仲裁利用的是差分电平和显性位覆盖隐性位的特性:谁先发到 ID 更小,谁就赢得总线。RS232 属于“谁是我”的问题,CAN 属于“我们是多主”的问题,这也是计算机导论里常拿这两个总线对比的原因。如果面试被问“从仲裁机制来说 RS232 属于什么总线”,答案是点对点全双工总线,它压根没有多主竞争,所以协议栈里也不存在仲裁字段。
2.4 同步、异步与握手:总线时序的两种基本模型
时序是总线里最容易让初学者崩溃的部分。同步总线由时钟统一驱动,所有信号在时钟沿被采样,例如 AHB 的每个传输都对齐 HCLK;异步总线没有公共时钟,靠请求与应答的握手信号推进,例如传统的 ISA 或者部分片内低速总线。
理解这一点比背时序图更有用:同步总线的时序参数是建立时间和保持时间,异步总线的关键参数是应答超时。调试时如果发现设备偶发读写失败,先确认是同步建立时间不足,还是异步应答没等到——两种问题的定位路径完全不同。同步总线上多数是等 1 拍就能稳住的;异步总线则需要看应答信号的时序余量。
3. 总线分类如何影响选型:从 AMBA 片上总线到 CAN 工业总线
3.1 片内总线与片外总线:AMBA 家族为什么这么重要
总线的第一层分类是按物理跨度。片内总线连接 CPU 核心、cache、内存控制器和外设控制器,片外总线则连接主板上的独立芯片。片内总线对延迟和布线面积极其敏感,所以协议往往更复杂、更强调流水线;片外总线则要考虑驱动能力、抗干扰和连接器成本。
AMBA 是 ARM 提出的片上总线架构,早期只分 AHB 与 APB,后来随着多核和高性能互连的发展又加入了 AXI。现在的 SoC 设计里,AXI 承担高性能通路,AHB 作为中速通路,APB 专门接管低速外设寄存器的配置,这个分层本身就是总线设计的经典范例。看 SoC 的 datasheet 时,先看互连框图里哪条通路走 AXI、哪条走 APB,就能大致判断带宽设计意图。
3.1.1 AHB 的流水线与 APB 的简单接口:一张表看懂分工
AHB 之所以比 APB 复杂,主要是因为流水线。AHB 允许当前传输与前一传输的地址阶段重叠,理想情况下每个时钟周期都能完成一次数据传输,并且支持突发,适合大块内存搬运。APB 的设计目标则是配置寄存器,它没有突发,也没有流水线,一个写周期要经过 SETUP 和 ACCESS 两个阶段,时钟频率也可以远低于系统主频。
下表是这两类总线在典型 SoC 中的定位差异。
| 总线 | 宽度(典型) | 是否支持突发 | 典型挂载设备 | 一句话定位 |
|---|---|---|---|---|
| AXI4 | 32/64/128 bit | 支持,可乱序 | DDR 控制器、DMA、GPU | 高带宽系统互连 |
| AHB | 32/64 bit | 支持 | 内存控制器、DMA | 中速高吞吐通路 |
| APB | 32 bit | 不支持 | UART、GPIO、SPI 控制器 | 低功耗寄存器配置口 |
3.1.2 AXI4 协议的高性能秘密:通道分离与乱序
AXI4 真正厉害的地方不是位宽更大,而是把读地址、读数据、写地址、写数据、写响应拆成五个独立通道,事务可以多笔同时进行,响应也可以乱序返回。这意味着 DMA 可以一口气发出多笔读请求,而不用等每一笔都回来再去发起下一笔,总线利用率因此大幅提升。
做 FPGA 或者 Zynq 开发时,AXI4 的 slave 接口通常需要自己实现通道握手,最坑的往往不是数据通路,而是响应的先后顺序:读通道和写通道的时序不匹配会导致死锁。处理办法也比较固定,就是严格按通道独立 FIFO 缓冲,然后保证响应完成信号只依赖本通道。
3.2 板级总线怎么选:SPI、I2C、RS485 的参数对比
板级总线是嵌入式开发真正天天打交道的东西。选择依据可以压缩成三个问题:需要多快?需要几个设备挂在同一条线上?是全双工还是半双工?SPI 四线制全双工,主设备用 CS 片选信号决定这一刻和哪个从机通信,速度可以跑到几十 MHz;I2C 只要两根线,靠协议里的 7 位地址区分设备,但每个字节都要等应答,速度上限低一些;RS485 是差分半双工,适合长距离多点通信。
| 总线 | 最少线数 | 双工方式 | 多机方式 | 典型速率 | 典型用途 |
|---|---|---|---|---|---|
| SPI | 4 | 全双工 | CS 片选 | 10~80 MHz | Flash、AD/DA、显示屏 |
| I2C | 2 | 半双工 | 7/10 位地址 | 100k~3.4 Mbps | 传感器、EEPROM |
| UART | 2 | 全双工 | 点对点 | 115200~数 Mbps | 调试口、GPS 模块 |
| RS485 | 2 | 半双工 | 地址帧轮询 | 最高 10 Mbps 级 | 工业采集、总线舵机 |
| CAN | 2 | 半双工 | ID 仲裁 | 最高 8 Mbps(FD) | 车载、机器人控制器 |
3.2.1 四线全双工与两线半双工:SPI 和 I2C 的本质差别
这里有一个容易忽略的点:SPI 没有从机主动上报的能力,所有通信都由主设备发起,CS 拉低就意味着总线被独占;I2C 虽然有地址,但从机不能连续发送,必须在主机发完读命令后由主机继续提供时钟,才能把数据推出来。
所以判断该用 SPI 还是 I2C,不是只看速度,还要看从机是否需要全双工、是否需要极低的引脚开销。ADC 采集高速数据一般用 SPI,温湿度传感器这类低频上报用 I2C 就够了。调试时也各有一招:SPI 先抓 CS 下降沿后 SCK 的边沿对齐,I2C 则先看起始位和应答位,哪个信号没出现就能顺藤摸瓜。
3.2.2 总线舵机与串行总线:信号线少时的多机控制思路
总线舵机是串行总线的一个很有代表性的应用。传统舵机一根信号线只能控制一个,总线舵机则把所有舵机都挂到同一条串行或 RS485 总线上,每个舵机烧录不同的 ID,主控发一帧包含 ID、目标角度、速度的指令,总线上的所有舵机都会收到,但只有 ID 匹配的那个执行。
这种设计把每设备一路控制线变成一总线多设备,省线、方便扩展,代价是控制周期受波特率和帧长限制。一个 1 Mbps 的串行总线上挂 8 个舵机、每帧 10 字节,刷新周期大约就是 8×10×10 微秒,即不到 1 毫秒,刚好够做关节控制。这个计算思路对总线选型和评估很有用。
3.3 汽车与工业总线:CAN、LIN 与 EtherCAT 的分工逻辑
汽车上的总线选择是按可靠性分级,而不是按速度分级。CAN 负责安全相关的动力域和底盘域,LIN 作为低成本低速总线接车窗、座椅这类不紧急的节点。CAN 帧结构里最值得关注的是仲裁段:11 位标准 ID(扩展帧为 29 位),ID 越小优先级越高。数据分析时,用 CAN 分析仪抓到的最多的不是数据段乱码,而是 ID 冲突导致的错误帧——两个 ECU 用了同一个 ID,报文会被错误地互相覆盖。
工业现场则有另一套逻辑:EtherCAT 属于工业以太网实时总线,数据帧在从站之间飞过,每个从站硬件实时抽取和插入自己的数据,循环周期可以做到 100 微秒级别。配置 EtherCAT 主站时,真正要调的不是网口速度,而是三个参数:通信周期、同步模式和 PDO 映射。运动控制上常见的做法是先把 PDO 映射表对齐伺服驱动器的对象字典,再调分布式时钟的偏移,否则会出现从站与主站时间的毫秒级错位,导致插补抖动。
4. 用 Linux 命令和模拟代码验证总线行为
4.1 /proc/iomem 与 lspci -tv:从系统视角看总线拓扑
总线看不见摸不着,但 Linux 把总线的拓扑暴露在了几个文件里。第一件该做的事,是查这台机器上的地址资源被谁占据:
cat /proc/iomem | head -30
这个文件列出物理地址空间的每一段分配给了谁。输出里常见的 System RAM 、 PCI Bus 、 IOAPIC 等标签,可以对照主板 memory map 理解地址译码的结果。再看设备树和拓扑:
lspci -tv
lsusb -t
lspci -tv 把 PCI 设备按总线号、设备号、功能号画成树,能看到设备挂在哪条 PCI 总线、桥后面还有多少设备; lsusb -t 展示 USB 控制器到底层设备的树形结构,每一层的 driver 是否绑定都能直接看到。这三个命令组合起来,能在一分钟内把一台机器的外部总线形态看明白。
逻辑说明:cat 输出的每一行都是“地址段—设备名”,head -30 是为了避免输出太长;lspci 的 -t 表示输出树形结构,-v 表示详细信息。参数说明:如果只要设备列表不带树形,用 lspci -nn 更直观; lsusb -t 里的 root hub 通常就是 CPU 内置 USB 控制器。
4.2 /sys/bus 与 Linux 驱动模型的匹配逻辑
Linux 驱动开发里的总线不只是物理连线,更是一套匹配框架。 ls /sys/bus 会列出系统里注册的所有总线类型:
ls /sys/bus
常见的输出里有 i2c 、 spi 、 pci 、 usb 、 platform 。设备(device)和驱动(driver)都挂在同一条总线目录下,内核的 bus_type 结构负责把它们配对。配对的依据是设备侧提供的 ID:PCI 设备用 vendor/device ID,I2C 设备用 compatible 字符串或 address,USB 设备用 idVendor/idProduct。
写驱动时常说 probe 没进来,排查顺序就是:设备是否在总线上被枚举(lsusb/lspci 能看到)、id_table 是否匹配、电源和复位是否就绪。驱动模型把这三件事解耦,理解“驱动不去找设备,总线帮助驱动找设备”,就抓住了 Linux 设备模型的核心。
4.3 用 Python 模拟一次固定优先级仲裁,理解状态机
理论上的仲裁机制,用一段可运行的模型模拟一次,比背十遍状态机都有效。下面这个例子用三个主设备的请求队列模拟固定优先级仲裁:
#!/usr/bin/env python3
# 主设备:id 用于识别,priority 为 0 表示最高优先级
masters = [
{"id": "CPU", "priority": 0, "requests": [1, 3, 5]},
{"id": "DMA", "priority": 1, "requests": [2, 4]},
{"id": "GPU", "priority": 2, "requests": [3]},
]
grant = []
for cycle in range(6):
# 筛选出当前周期已经发起请求的主设备
active = [m for m in masters if m["requests"] and m["requests"][0] <= cycle]
if not active:
grant.append(None)
continue
# 固定优先级:priority 最小者获得总线使用权限
active.sort(key=lambda m: m["priority"])
winner = active[0]
grant.append(winner["id"])
winner["requests"].pop(0)
print(grant)
逻辑说明:每个主设备有一个请求时间点队列,程序按周期扫描,取出当前周期已到期的请求,再用固定优先级规则选出获胜者;获胜者的第一个请求被弹出,表示该请求消耗了一次总线占用。参数说明: requests 中数字表示在第几个时钟周期发出请求; priority 数值越小优先级越高。
运行结果会看到 GPU 在周期 3 提出请求,但 CPU 和 DMA 的请求持续到来,GPU 一直拿不到总线——这正是固定优先级仲裁饿死现象的模型化表达。如果想观察轮询的效果,把排序方式改为按 id 顺序轮转即可,二者在公平性上的差异立刻可见。
4.4 总线调试时最常遇到的三个坑
4.4.1 板级:485 布线中的 A/B 接反与终端电阻
RS485 总线调试排在第一位的永远是 A、B 线是否接反,其次是终端电阻。标准做法是总线两端各接一个 120 欧终端电阻,中间节点不接;如果总线空闲时读到不定态,通常就是终端电阻缺失或 A/B 接反。调试时先量 A-B 间静态电压,大于 200mV 才算正常。布线规范上,485 走双绞线是为了让差分信号共模抑制,地线也要在末端单点连接,而不是在每个节点都接地。
4.4.2 系统级:SM Bus 控制器驱动缺失与地址冲突
有一个非常常见的系统级总线问题是 SM Bus。重装 Windows 后设备管理器里出现带感叹号的 SM Bus Controller,错误代码 28,经验值判断大多是芯片组 INF 驱动没有安装,而不是硬件故障。SMBus 可以看作 I2C 总线的变体,常挂在 PCH 内部,用来读内存 SPD、温度传感器和电源管理芯片。忽略这个感叹号短期内可能不影响使用,但会造成内存温度读取失败,也会让部分商用机的风扇策略失效。处理办法是安装主板芯片组驱动包,让系统识别出 PCH 内部的总线控制器。
4.4.3 协议级:逻辑分析仪采样率和协议解码的选择
抓总线时序,逻辑分析仪的采样率必须大于信号最高频率的 4 倍,否则边沿会被采丢,解码结果完全不可信。抓 SPI 时,4 通道配置为 CLK、MOSI、MISO、CS,先看 CS 拉低是否干净、SCK 是否有毛刺,再去看数据;抓 I2C 时先找起始位和应答位,ACK 一直为高通常是从机没响应。协议解码能节省时间,但不要把解码结果当成唯一依据,关键时刻要回到波形本身评判。
5. 总线性能不是看频率:带宽公式、突发传输与瓶颈口算
5.1 总线带宽基础公式的两个修正项
常写的总线带宽公式是:带宽 = 总线宽度 × 工作频率。这个式子只适用于理想状态,实际要乘以协议效率。比如 32 位 AHB 跑 100 MHz,理论带宽 400 MB/s,但每个传输之间可能有等待周期、读后写还要切换方向、地址阶段也要占周期,实际测量通常只有理论值的 60%~70%。所以更实用的公式是:有效带宽 = 宽度 × 频率 × 协议效率。协议效率不是常数,它取决于突发长度和传输模式。
5.2 突发传输和 DMA 为什么能显著提高有效带宽
突发传输的价值在于:一次仲裁获得总线后连续传输多拍数据,省掉每次传输的地址阶段和重新仲裁的开销。DDR 的突发长度一般是 8,PCIe 的最大写载荷是 256 字节,如果每次都只传 4 字节,协议头开销就占了大部分。做 DMA 驱动时,常见做法是尽量把分散的小块数据聚合到一块缓冲区,让 DMA 发起更长的事务。这里有个经验值:当总线利用率低于 50% 时,先查是不是单次传输太短,再考虑提升频率——加频率解决不了协议开销问题。
5.3 口算判断一条总线是否为瓶颈
这里给一个平时做系统性能评估时常用的口算顺序。第一,算理论带宽;第二,按负荷类型估效率,大块搬运按 80%,寄存器读写按 30%;第三,对比实际负载需求,余量小于 2 倍就要警惕。比如 PCIe 3.0 x1 的编码后有效带宽约 985 MB/s,千兆网卡满速 118 MB/s,网卡流只能占到总线的 12%,这不是瓶颈;但如果是多块 NVMe 同时跑,就要重新计算了。最后检查一下工具链:用 perf stat 看 cycles 和 stalled-cycles 的比例,stalled 占比过高时优先怀疑的是 cache miss 和总线延迟,而不是主频。总线问题大多发生在资源利用率还没到 100%,延迟却已经明显变差的时候,这时候把判断点从频率转移到协议效率上,方向才对。
301



被折叠的 条评论
为什么被折叠?



