WarmGrayMatteInkMistClaySage
RELIEF · HARDWARE

Seven hardware diagrams, drawn in relief七种硬件框图,用凹凸画出来

Every shape on this page carries meaning. Raised is a thing that exists; sunken is a place you cannot reach, a condition, or a channel cut into the surface. Nothing here is decoration — if a block is pressed in, that is the diagram telling you something.这一页上每个形状都有意思。凸起是一个存在的东西;凹陷是你够不到的地方、一个条件、或者刻进面料的一道槽。没有一处是装饰 —— 一块凹进去,是图在告诉你一件事。

A · State machineA · 状态机

States are raised blocks, transitions are embossed lines, and each condition sits in a sunken pill. Sunken means condition, raised means state — the reader never needs a legend. The entry state carries the accent colour. Below are the kernel's four runtime-PM states.状态用凸起的块,迁移用浮雕线,条件写在凹进去的药丸里——凹的是条件,凸的是状态,不用看图例也分得清谁是谁。入口状态给强调色。下面画的是内核 runtime PM 的四个状态。

RUNTIME PM STATE MACHINERUNTIME PM 状态机the failure path back to ACTIVE is the line most diagrams leave out失败回退那条线是重点,多数图会漏掉
ACTIVEin use设备在用
SUSPENDINGsuspend callback running正在调 suspend
SUSPENDEDpowered down已掉电
RESUMINGresume callback running正在调 resume
usage count hits zero引用计数归零
suspend returned 0suspend 返回 0
accessed · get_sync()被访问 · get_sync()
resume returned 0resume 返回 0
suspend returned −EBUSYsuspend 返回 −EBUSY
get() / put() only move the count, not the stateget() / put() 只改计数,不换状态

B · Timing diagramB · 时序图

The waveforms live inside a sunken panel — it is a screen, so sunken is the honest shape. Traces are embossed strokes floating on it; alignment guides and measurement bars sit one layer below in the surface colour, so they never compete with the traces. Below is a panel power-on sequence.波形放进一块凹陷的面板里——它本来就是一块显示屏,凹进去比凸出来对。信号线用浮雕描边浮在面板上;基准虚线和量取条用面料色,压在波形下面一层,不抢。下面是一块屏的上电时序。

PANEL POWER-ON SEQUENCE屏上电时序the four delays are what gets missed when porting to a new panel四段延时是换屏时最容易抄漏的东西
VCI panel analog rail面板模拟电源 VDDI IO railIO 电源 RESETn active-low reset低有效复位 MIPI DSI commands / video stream命令 / 视频流 init commands → first frame初始化命令 → 首帧数据 backlight背光 BL PWM enablePWM 使能 t1 ≥ 1ms t2 ≥ 10ms t3 ≥ 120ms t4 ≥ 2 frames after first framet4 首帧后 ≥ 2 帧

C · Register bitfieldC · 寄存器位域

Reserved bits are sunken dead zones, usable bits are raised — you know which bits you may touch without reading the access column. The write-only self-clearing bit takes the accent colour, because it is the one people get wrong: it always reads back 0, and that does not mean the write missed.保留位画成凹进去的死区,能用的位凸起——不用读属性列就知道哪些位是能碰的。只写自清的位给强调色,因为它是最容易写错的一类(读回来永远是 0,不代表没生效)。

Quartz-3550 · DSI_CTRLQuartz-3550 · DSI_CTRLoffset 0x0010 · reset 0x0003_FF00偏移 0x0010 · 复位值 0x0003_FF00
31 ······ 20
19·16
15 ··· 8
7·5
4
3
2
1
0
RSVD
LANE_NUM0x3
TIMEOUT0xFF
RSVD
LP_MODE
ERR_IE
DONE_IE
RESET
ENABLE
reset value复位值 0x0003_FF00 write 0 to reserved bits; read-back is not guaranteed保留位写 0,读回不保证 RESET is write-only self-clearing · always reads back 0RESET 位只写自清 · 读回恒为 0
Bits位Name名称Access属性Reset复位Notes说明
31:20RSVDRO0Reserved. Write 0. Read-back is not guaranteed — never branch on it保留。写 0;读回值不保证,不要拿来做判断
19:16LANE_NUMRW0x3Data lane count minus one. 0x3 = four lanes数据通道数减一。写 0x3 = 四通道
15:8TIMEOUTRW0xFFCommand timeout in byte-clock cycles. 0 = never time out命令超时,单位为字节时钟周期。写 0 = 不超时
4LP_MODERW01 = send commands on the low-power lane. Must be 1 while sending init commands1 = 命令走低功耗通道。发初始化命令时必须为 1
3ERR_IERW0Error interrupt enable错误中断使能
2DONE_IERW0Transfer-done interrupt enable传输完成中断使能
1RESETWO0Write 1 to reset the controller; hardware clears it. 写 1 复位控制器,硬件自清。Always reads back 0 — you cannot tell from the register whether the reset happened读回恒为 0,不能用读回值判断复位是否做过
0ENABLERW0Controller master enable. Clear it before changing any other field控制器总开关。改其它位前应先置 0

D · IP block diagramD · IP 内部框图

Groups sit in sunken wells, modules are raised blocks inside them — a well says these belong together, a block says this is one thing. The bus is a sunken rail: masters attach above it, slaves below. That is the reading convention; break it and every reader has to trace each line to find who initiates a transfer.分组用凹陷的槽装,模块用凸起的块摆进去——槽是「这几个归一起」,块是「这是一个东西」。总线画成一条凹槽轨:主设备接在轨上方,从设备接在下方,这是读图的约定,不按这个摆,看图的人得逐条线追才知道谁发起访问。

Quartz-3550 application processor · internal structureQuartz-3550 应用处理器 · 内部结构illustrative name, not a real product示意名,非真实产品
CPU subsystemCPU 子系统 master主设备
Core A ×4big cores · 2.0GHz大核 · 2.0GHz
Core B ×4little cores · 1.5GHz小核 · 1.5GHz
L3 Cache1MB shared1MB 共享
Coherency port一致性接口snoop bus侦听总线
Accelerators加速器 master主设备
GPUgraphics图形
NPUinference推理
DMAbulk copy搬运
SYSTEM INTERCONNECT · AXI系统互连 · AXImasters above · slaves below主设备在上 · 从设备在下
Storage存储 slave从设备
DDR controllerDDR 控制器
DDR PHY
On-chip SRAM片上 SRAM256KB
eMMC / SD
Display & media显示与多媒体 slave从设备
VOPdisplay output显示输出
MIPI DSI
ISP
Video codec视频编解码
Peripherals外设 slave从设备
I2C ×6
SPI ×3
UART ×8
GPIO ×5
PWM ×4
USB
System control系统控制 slave从设备
GICinterrupts中断
CRUclock & reset时钟复位
PMUpower domains电源域
OTPfuses熔丝
Crypto
Master: initiates bus transfers on its own主设备:自己发起总线访问 Slave: only responds, never initiates从设备:只响应,不发起 The block this page is about本次讨论涉及的模块

E · Memory mapE · 内存布局

The address space runs top to bottom and anything you cannot reach is drawn as a groove — reserved regions, holes, the secure world. The right-hand column says what each region is for, because that is what a reader of this diagram actually asks. Not how big it is.地址空间从上往下排,访问不到的区间画成凹槽——保留区、空洞、安全世界,凹下去的一眼就是「这块你碰不了」。右边留一列写用途,因为读这种图的人真正要问的是「这块归谁」,不是「它多大」。

Quartz-3550 · physical address spaceQuartz-3550 · 物理地址空间leave the TEE region out of reserved-memory and the kernel allocates into it, then dies laterTEE 保留区没在设备树里 reserve 掉,内核会分配进去,跑着跑着就挂
0xFFFF_FFFF
0x87E0_0000
Usable system memory可用系统内存this is what the kernel buddy allocator manages内核 buddy 分配器管的就是这段
≈1.9 GB
0x8660_0000
framebuffer reservedframebuffer 保留the display controller fetches from here — it cannot be moved显示控制器直接取数,不能被搬走
24 MB
0x8260_0000
CMA contiguous poolCMA 连续内存for devices that need large physically contiguous buffers给要物理连续大块的外设
64 MB
0x8060_0000
Kernel image内核镜像where the decompressed Image landsImage 解压后落在这
32 MB
0x8040_0000
ATF / BL31resident — never overwrite常驻,不能覆盖
2 MB
0x8000_0000
TEE reservedTEE 保留secure world only · reads back all zeroes from the non-secure side安全世界独占 · 非安全侧读回全 0
4 MB
0x4000_0000
Hole空洞nothing responds here · an access raises an external abort没有任何东西响应 · 访问触发外部中止
1 GB
0x2000_0000
Peripheral register window外设寄存器窗口this is the range ioremap maps inioremap 映射进来的就是这段
256 MB
0x0010_0000
On-chip SRAM片上 SRAMcode runs here before DDR is trainedDDR 还没初始化时,代码跑在这
256 KB
0x0000_0000
BootROMmask ROM · fixed at manufacture, cannot be changed掩膜只读 · 出厂固化,改不了
1 MB

F · Data pathF · 数据通路

Stages run left to right and under each one is what it turned the data into — a data path drawn as a row of boxes leaves the reader still not knowing what happened in between. Places that store data use the deep block; places that transform it use the plain raised block.一级一级往右走,每级底下写它把数据变成了什么——数据通路图最容易画成「几个盒子连起来」,那样看完还是不知道中间发生了什么。存数据的地方用深色块,加工数据的地方用普通凸块,两类分开。

DISPLAY PATH · one frame from memory to glass显示通路 · 一帧从内存到屏the DMA lives in the display controller, not in the DSI blockDMA 在显示控制器里,不在 DSI 里
DDRframebuffer
1080×2400×4B
≈9.9 MB / frame≈9.9 MB / 帧
AXI read channelAXI 读通道DMA fetchDMA 搬运
burst read突发读
128-bit wide128 bit 位宽
Layer blend图层合成VOP
multi-layer多层叠加
scale · crop缩放 · 裁剪
Colour convert色彩转换gamma · ditherGamma · 抖动
RGB888
→ panel bit depth→ 面板位深
DSI packetiseDSI 打包add header + ECC加包头校验
pixel stream像素流
→ packets→ 数据包
D-PHY serialiseD-PHY 串化parallel → serial并转串
4 lane
differential pairs差分对
Panel面板driver IC驱动 IC
60 Hz
line by line逐行刷新
Whole-path bandwidth ≈ 594 MB/s (9.9 MB × 60 Hz)整链带宽占用 ≈ 594 MB/s(9.9 MB × 60 Hz)58% of the 1.03 GB/s DDR theoretical bandwidthDDR 理论带宽 1.03 GB/s 的 58%

G · Clock treeG · 时钟树

The mux and the gate in a clock tree already are controls — picking one of the divided outputs is a segmented control, enabling the branch is a switch. Draw them as the controls they are and the reader learns no new symbols, while which path is live reads at a glance.时钟树里的选择器和门控本来就是控件——分频后选哪一路是个分段控件,开不开这条时钟是个开关。直接拿控件画,不另造图形:看图的人不用学新符号,而且哪一路是通的一眼看得出。

DISPLAY CLOCK · crystal to pixel clock显示时钟 · 从晶振到像素时钟with the gate closed a register read in that branch hangs — the register is not broken门控关着的时候读寄存器会挂,不是寄存器坏了
Source时钟源
OSC
24 MHz crystal24 MHz 晶振
PLL_VIDEO
×49.5 → 1188 MHz
Dividers分频
÷ 2
594 MHz
÷ 4
297 MHz
÷ 8
148.5 MHz
three parallel branches, all hanging off PLL_VIDEO三路并联,都挂在 PLL_VIDEO 上
Mux选一路
594297148.5external外部
only the selected branch continues downstream选中的这一路才往下走
Gate门控
CLK_VOP_EN  with it closed, every register below this branch reads all zeroes or hangs outright关着的时候,这一支下面所有寄存器读回全 0 或直接挂
Leaf clocks叶子时钟
dclk_vop
297 MHz · pixel clock297 MHz · 像素时钟
aclk_vop
297 MHz · bus clock297 MHz · 总线时钟
hclk_vop
148.5 MHz · register clock148.5 MHz · 寄存器时钟

H · Cache line statesH · 缓存一致性状态

Four states, and the one that costs you is S — the accent marks it because writing to a shared line is the transition that has to stop every other core first. The dashed edge is that write. A driver that memcpy()s into a buffer another master is reading lives on that dashed line.四个状态,代价最大的是 S —— 给它强调色,是因为往一行共享数据里写,这次跳转必须先把别的核全叫停。那条虚线就是这次写。一个驱动往别的主设备正在读的缓冲区里 memcpy,走的就是这条虚线。

MESI · one cache lineMESI · 一行缓存this is why a DMA buffer needs either a flush or a coherent allocation — not an opinion, a state transition这就是为什么 DMA 缓冲区要么刷缓存要么用一致性分配 —— 这不是风格问题,是状态跳转
EExclusive · clean, only this core has it独占 · 干净,只有本核有
MModified · dirty, only this core has it已改 · 脏数据,只有本核有
SShared · clean, other cores have copies共享 · 干净,别的核也有副本
IInvalid · this line is stale失效 · 这行数据过期了
this core reads, no other copy exists本核读取,别处没有副本
this core writes本核写入
another core reads it别的核来读
another core writes it别的核来写
write to a shared line — every other copy must be invalidated first写一行共享数据 —— 必须先把其它副本全部作废

I · DMA descriptor chainI · DMA 描述符链

Each descriptor is a raised block and its next pointer is the groove between them. The last one has no next, so that slot is drawn as a dead groove rather than a value — the chain ending and a value being present then look different, which matters because a descriptor left pointing at freed memory is the bug this figure is about.每块描述符是凸的,它的 next 指针就是块之间那道凹槽。最后一块没有 next,所以那一格画成凹陷的死区而不是一个值 —— 这样「链在这里结束」和「这里有个值」长得不一样,而这很要紧,因为描述符指向已经释放的内存正是这张图要讲的那个 bug。

SCATTER-GATHER LIST分散聚集链表the ringed one is where the engine is right now — read it while the engine runs and you get a torn value描圈那块是引擎当前所在。引擎在跑的时候去读它,读到的是撕裂的值

DESC 0

buffer缓冲区
0x8720_0000
length长度
4 KB
next
→ DESC 1

DESC 1

buffer缓冲区
0x8721_0000
length长度
4 KB
next
→ DESC 2

DESC 2

buffer缓冲区
0x8722_0000
length长度
2 KB
next
NULL

J · Bus transaction timingJ · 总线事务时序

Protocol level, not electrical level — the question a driver author brings here is which beat stopped getting acknowledged. The two measure bars name the two failures that look identical from userspace: no ACK on the address means nobody answered, no ACK on the register means the chip is there but does not know that register.这是协议层不是电气层 —— 写驱动的人来看这张图,问的是从哪一拍开始没人应答。底下两条量取条标出的,正是从用户态看长得一模一样的两种失败:地址没 ACK 是根本没人答,寄存器没 ACK 是器件在、但不认这个寄存器。

I2C WRITE · one register addressI2C 写 · 一个寄存器地址an analyser shows the same picture; this one labels what each missing ACK means逻辑分析仪抓出来的就是这张图,这里多标了每个缺失的 ACK 各自意味着什么
SCL SDA 7-bit addr + W START addr 0x38 + W ACK reg 0x00 ACK no ACK here = wrong address, or nobody home这里没 ACK = 地址写错,或者器件根本不在 no ACK here = the chip is there but does not know that register这里没 ACK = 器件在,但不认这个寄存器

Terms used above上面用到的术语

A diagram that needs a word the reader does not have is not a diagram, it is a quiz. Every term below appears somewhere on this page.一张图要是用了读者没有的词,那不是图,是考试。下面每个词在这页上都出现过。

fetch取数 · fetch
the display controller issues its own bus reads to pull a frame out of memory — the CPU does not copy it there.显示控制器自己发起总线读,把一帧像素从内存搬进来。不是 CPU 拷贝给它的。
physical address物理地址 · physical address
the address that actually appears on the bus. Most addresses in kernel code are virtual; page tables map between them.硬件总线上真实的地址。内核代码里看到的多数是虚拟地址,两者靠页表对应。
coherency一致性 · coherency
when several masters each hold a cache, keeping what they see of the same memory identical. Without it you flush caches by hand.多个主设备各有缓存时,保证它们看到的同一块内存内容相同。做不到就得手工刷缓存。
burst突发 · burst
one bus transaction carrying several beats of data instead of one address per beat. Fetching a whole frame relies on it.一次总线事务连续搬多拍数据,而不是一拍一个地址。取整帧像素靠的就是它。
on-chip SRAM片上 SRAM · on-chip SRAM
a small memory inside the chip, usable the moment power is up. Early boot code runs here because DDR is not trained yet.做在芯片里的一小块内存,上电就能用。DDR 还没训练好之前,早期代码只能跑在这。
device tree设备树 · device tree
a text file describing what hardware is on the board and which address range each piece owns; the kernel reads it at boot.一份描述板上有哪些硬件、各自占哪段地址的文本文件,内核启动时读它。
clock gate门控 · clock gate
a switch deciding whether this clock branch continues downstream. With it closed the modules below simply do not run.一个开关,决定这一支时钟往不往下走。关着的时候下游模块整个不工作。
divider分频 · divider
divides a clock down to a lower frequency. One PLL usually feeds several parallel branches at different rates.把时钟频率整除成更低的一档。一个 PLL 常常并联出好几路不同频率。
bitfield位域 · bitfield
a register's 32 bits cut into runs, each run controlling one thing.把一个寄存器的 32 位切成几段,每段各管一件事。
self-clearing自清 · self-clearing
writing 1 triggers an action and the hardware clears the bit itself, so it always reads back 0.写 1 触发一个动作,硬件做完自己把这位清回 0。所以读回来永远是 0。