尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

从芯片启动到系统集成:SoC开发十年实战经验总结

从芯片启动到系统集成:SoC开发十年实战经验总结 2014 SoC Conference 的早鸟注册是周一早上 9 点开放的我在办公室看到邮件立刻把差旅申请给交了。当时组里不少人觉得一个技术会议而已早鸟不早鸟能差多少。后来我数了一下那届会议笔记里至少有三分之一的技术点直接对应到之后三年项目里碰过的真问题剩下的三分之二则是帮我提前看到了要踩的坑。这篇文章不打算复述会议议程只聊聊我在那届会议前后积累的 SoC 开发经验尤其是这十年里反复被问到的启动、电源、时钟、工具链和系统集成话题。1. 早鸟注册已开启这次 SoC 大会值得你掏出预算1.1 那届会议正好处在 SoC 架构转型的节点2014 年前后的 SoC 行业其实处在一个很有意思的转型期。单核 CPU 加简单外设的老路还在走但异构 SoC 已经开始冒头一边是手机 SoC 把 modem、ISP、GPU 全部塞进去另一边是 FPGA 厂商开始认真做“FPGA ARM”的异构方案Xilinx Zynq-7000 已经在不少工业项目里落地用户第一次意识到原来“可编程逻辑 处理器系统”可以放在同一颗芯片里。也正是那一年很多做嵌入式的人开始把“SoC”挂在嘴边但真正理解 SoC 启动流程、电源域设计和调试链路的人并不多。我之所以说这次的早鸟注册值得关注是因为这类大会的议程密度决定了它很适合用来建立知识坐标系。参会前我习惯先把热词过一遍2014 年是 ARM 多核、MIPI、DDR4、虚拟化放到现在再提 SoC 时大家搜出来的是什么soc芯片启动、rf soc器件gen3 adc电源纹波、versal adaptive soc clocking resources、simulink soc、海光soc芯片组驱动。你会发现问题已经从“SoC 能做什么”变成了“SoC 怎么调好、怎么量产、怎么驱动”。这说明行业已经过了概念普及期现在大家关心的是工程落地。所以与其说是去听一场会不如说是去给自己补一张完整的 SoC 工程地图。早鸟注册阶段通常还会开放少量动手工作坊这些名额比正价票更值得抢。毕竟技术大会的 PPT 之后多半能看到资料的但工作坊里能摸到的板子、能面对面问到的 FAE才是真正买不到的信息差。1.2 早鸟票省下的不止是预算还有技术信息差早鸟注册这个动作很多人只理解成“便宜几百块钱”实际上对技术人来说更重要的是你可以提前拿到完整议程并且有时间做功课。我通常的做法是先把所有和自己垂直领域相关的议题标出来再给每个议题列出一个“我现在最想解决的问题”到现场直接带着问题去听。比如那届会议上有一场关于 Zynq 裸机启动的分享如果不是提前看过议程我大概率会因为名字太基础而跳过结果现场那场恰恰帮我解决了一个 PMU 固件加载失败的问题。另外早鸟阶段报名一般还能优先预约厂商技术交流时间。这个环节看起来像是厂商的市场活动实际上是最值钱的“咨询时段”。我有一次带着板子的启动日志去约谈现场工程师扫了五分钟日志就直接指出是我没烧写 PMU 固件导致的。这种问题如果在官网论坛上发帖可能要来回两三天在会议现场二十分钟就定位了。所以如果你确定手头有 SoC 相关的项目要推进看到早鸟开放就别犹豫先占坑再慢慢规划行程。2. 从芯片启动到运行SoC 开发的第一道坎2.1 SoC 芯片启动流程拆解BootROM 到 PMU很多人第一次接触 SoC 开发时最容易栽跟头的不是应用逻辑而是芯片根本跑不起来。这里的“跑不起来”往往不是硬件坏了而是启动流程没搞清楚。SoC 和单片机最大的区别在于芯片内部不是一个简单的中断向量表就能搞定启动的它有一整套 BootROM、启动模式引脚、固件加载器和安全校验流程。拿常见的 Xilinx RFSoC 平台来举例。芯片上电之后BootROM 会先执行一段固化在芯片里的引导代码根据模式引脚决定从 QSPI、SD 卡、JTAG 还是网口加载 FSBLFirst Stage Bootloader。FSBL 再负责初始化 DDR、时钟和串口然后加载 PMU 固件。这时候就有一个高频问题冒出来了xilinx rf soc裸机需要pmu文件吗答案是需要除非你只想让处理器核空转。PMUPlatform Management Unit负责电压、温度、电源域和部分时钟管理裸机应用不启动 PMU 固件系统随时可能因为电源事件或者时钟配置异常而死机。我见过不止一个工程师在 SDK 里直接跳过 PMU 固件觉得“我不用 Linux裸机没必要搞这么复杂”。结果代码跑到一半核心电压调节器报中断整个系统直接挂死。所以我现在做任何 SoC 项目拿到板子的第一件事就是把官方 BSP 里的启动镜像完整构建一遍确认 FSBL、PMU、ATF、应用镜像这条链路是通的再开始改自己的逻辑。不是每一颗 SoC 都叫单片机启动流程里的每一级都有它存在的理由。2.2 裸机、Linux 还是 RTOS先想清楚 PMU 文件和服务固件选操作系统这件事在 SoC 项目里往往不是“哪个好”的问题而是“你有没有能力维护完整软件栈”的问题。早期很多团队为了“简单”选裸机结果后面要做网络协议栈、文件系统、OTA 升级时发现全部要自己写。而选 Linux 的团队又常常被设备树、内核版本、根文件系统和驱动调试搞得焦头烂额。从我这边的经验看可以按这几个维度决策实时性要求微秒级确定性控制选裸机或 RTOS毫秒级事件处理选 Linux 完全够用。外设复杂度USB、Wi-Fi、蓝牙这类协议栈复杂的外设直接上 Linux 内核驱动省下的开发时间非常可观。安全隔离需求需要多个核心跑不同系统的可以选 AMP非对称多处理例如 Linux 跑应用、裸机跑实时控制。启动维护成本选 Linux 就意味着要接受 PMU 固件、ATF、U-Boot、内核四个阶段都要维护裸机则至少也需要 FSBL 和 PMU 固件。PMU 固件这件事在 Linux 启动链里同样重要。U-Boot 和内核都会调用平台管理接口如果你用的 PMU 固件版本和芯片版本不匹配经常会出现奇怪现象内核启动一半报硬件错误、DDR 带宽测试不达标、温度传感器读数恒为 0。解决思路是保证 PMU 固件版本与 Vitis/SDK 版本、芯片版本在官方兼容表里对齐而不是随意拿一个工程目录下的旧镜像凑合用。2.3 Linux SoC 开发中常见的设备树陷阱既然是 SoC就绕不开 Linux。这几年我帮不少人排查过“内核起来了外设一访问就崩溃”的问题十有八九是设备树写错了。设备树不是简单的寄存器地址罗列它描述的是整个 SoC 的拓扑关系中断控制器挂在哪个总线域、时钟源怎么走、DMA 通道优先级、引脚复用和电源域依赖。一个典型坑是时钟依赖没写全。比如某个外设的时钟来自 SoC 内部 PLL设备树里只配了使能位、没配父时钟频率驱动调用 clk_get_rate 拿到一个 0于是开始用默认超时值表现为功能异常但不是完全不能用。调试这种问题特别费时间因为 dmesg 不一定有报错。我建议在 bring-up 阶段先把设备树里的clocks、assigned-clocks和assigned-clock-rates全部显式写清楚宁可多写不要少写。另一个常见坑是 DMA 内存范围。SoC 里的 DMA 不一定能访问全部 DDR有些只能访问特定地址范围。设备树里如果忽略dma-ranges约束驱动申请缓冲区时可能会从不可访问的地址取内存结果是 DMA 传输长时间不完成或者抛 CM 错误。具体现象因芯片而异但只要出问题优先拿逻辑分析仪看总线访问地址再回头查设备树。Linux SoC 开发本质上是一场“硬件描述和驱动需求对应”的修行所有玄学问题最后都能在设备树和芯片手册里找到答案。3. 高速数据通道背后的模拟细节RFSoC 与电源纹波3.1 RFSoC Gen3 ADC 为什么会受电源纹波影响如果说启动和 Linux 是 SoC 开发里的“数字逻辑问题”那么当你开始用 RFSoC 这类芯片时就会突然面对一大堆模拟细节。RFSoC 的关键卖点是射频直采Gen3 器件的 ADC 可以采样到 GHz 频段意味着中频甚至射频信号可以直接进 ADC。但这也带来了一个非常现实的问题电源纹波会直接影响 ADC 的动态性能。很多人以为 ADC 的精度只取决于位数实际上有效位数ENOB会被电源质量严重拉低。RFSoC 内部的高速采样时钟通常来自片内 PLL 或者外部参考钟采样时钟的抖动会直接转化为电压噪声如果你的供电电压上叠加了几毫伏的纹波而纹波频率落在信号带宽内就会在 ADC 输出频谱里形成杂散SFDR 和 SNR 双双下降。更麻烦的是纹波不一定来自 DC-DC还可能是高速数字核产生的开关噪声通过共享电源平面耦合过去的。我在实际项目里测过一组数据同一块 RFSoC 板卡在开关电源输出直接供电的情况下ADC 在 2.4GHz 频点附近的 SFDR 是 62dBc换用 LDO 加 π 型滤波之后同样条件下 SFDR 提升到 71dBc。这 9dB 的差距不是靠算法能补回来的。所以做 RFSoC 类 SoC 设计电源纹波一定要在前端就控制住。3.2 电源纹波实测与去耦方案电源纹波的项目经验可以拆成三块测试、布局、器件选型。测试方面不要只信 DC-DC 数据手册上写的纹波指标。那是在理想负载下测出来的和实际 PCB 上的纹波完全不是一回事。正确做法是拿示波器加带宽限制一般设 20MHz 或更高RFSoC 场景建议至少 200MHz用短地弹簧或者同轴线直接在芯片电源引脚的测试点上测。近场探头配合频谱仪也很有用可以看到纹波的具体频率成分判断是开关频率基底、边沿振铃还是数字噪声耦合。布局方面RFSoC 的电源去耦必须遵守“就近、低感、大平面”三个原则。电容要尽量靠近对应的电源引脚过孔要直接打到主电源平面不能先走一段线再打孔。混合去耦配置通常是 100nF、10nF、1nF 搭配若干 22uF 钽电容或陶瓷电容覆盖从低频开关纹波到高频谐振的频段。还要特别留意模拟电源和数字电源的物理隔离至少不要交叉走线。器件选型方面如果成本允许RFSoC 的 AVCC、ADC 供电轨尽量选用高 PSRR 的 LDO并且后级加磁珠和电容滤波。DC-DC 不是不能用但输出级一定要再经过一级低噪声供电才能进模拟域。我踩过的坑是磁珠选型只看直流电阻没看阻抗曲线结果磁珠和板上的电容在某几个 MHz 频点产生并联谐振反而放大了纹波。现在我的习惯是拿到磁珠样品后直接用网络分析仪扫一下阻抗曲线再决定是否装到 RFSoC 电源路径上。3.3 Versal 自适应 SoC 的时钟资源阅读方法时钟是 SoC 的老话题到了 Versal 自适应 SoC 这一代时钟资源比之前的 Zynq 要复杂不少。Versal 里有专门的 Clocking Resources分布在不同的列和区域里和传统的全局时钟缓冲、MMCM/PLL 并不完全一样。如果你直接拿旧经验去配时钟很容易发现寄存器地址都对不上或者某些区域根本没有可用的时钟资源。Versal 自适应 SoC 的时钟资源架构在官方文档《Versal Adaptive SoC Clocking Resources Architecture Manual》里有完整描述但那本手册非常厚直接读很容易晕。我建议先抓三条主线系统时钟树从外部晶振或参考时钟进入芯片后如何分配到 CPU、NoC 和各功能块。可编程逻辑时钟FPGA 逻辑阵列里的时钟区域如何用 BUFGCE、BUFG_PS、区域时钟等资源实现。高速收发器时钟PCIe、以太网、RF 数据转换器的参考钟如何从引脚进入在哪个模块里完成分频和锁相。我在做一个 Versal 项目时遇到过一个问题PL 侧逻辑跑 400MHz但 NoC 的时钟频率没配够导致 DMA 从 PS 侧访问 PL 数据的时候延迟抖动严重。当时调了很久最后把时钟约束报告打开看到 NoC NPI 频率只跑到标称值的 60%才意识到是时钟初始化代码里少了 NoC PLL 的配置。从那以后我做 Versal 项目一定会先看两样东西一个是时钟约束报告一个是 FPGA 的时序收敛报告两者配齐了才开始写业务逻辑。4. 从模型到硬件Simulink SoC 与调试环境4.1 Simulink SoC 工作流怎么搭这些年 SoC 开发工具链越来越抽象化Simulink SoC 就是典型代表。它把 FPGA 和处理器放到一个建模环境里自动生成软硬件接口代码。对于不熟悉 RTL 和 C 跨界集成的团队这个工作流能省下非常多的时间。我自己的使用路径是先建一个顶层模型把处理器固件部分和 FPGA 逻辑部分用 SoC Blockset 的模块连接起来比如 AXI Master、AXI Slave、DMA 和中断模块。模型跑通后再自动生成代码Simulink 会把处理器侧生成 C 代码把 PL 侧生成 HDL并且自动生成设备树和硬件抽象层。这样做的最大好处是接口定义不会走样软件看到的寄存器地址和硬件的 AXI 地址天然一致不容易出现“驱动里写 0x40000000 但实际 RTL 里挂在 0x50000000”这种低级错误。但这套工具链也不是没有坑。生成代码默认会带上很多运行时支持库如果不做裁剪生成的二进制体积可能比手写大不少在资源紧张的 SoC 上可能放不下。另外Simulink 的模型仿真相对于真实硬件有时序差异尤其是 AXI 总线上的背压和 FIFO 水位模型里表现得比较理想上板后可能会遇到吞吐量下降。我一般会先用模型做功能验证再在上板阶段用硬件在环模式对拍几个关键场景防止模型和实现“两层皮”。4.2 调试器连不上目标 VM 的排查记录硬件调试和模型仿真之间还有一个绕不开的环节开发板或者虚拟目标连不上。这几年我用 Xilinx Vitis/SDK 调试时见过一个很经典的报错disconnected from the target vm, address: 127.0.0.1:57436, transport: soc。第一次看到这个报错我以为是网线没插好折腾了很久才发现问题根本不在物理层。这个报错通常出现在连接本机回环地址上的调试虚拟机它需要调试器和目标机的调试服务进程完成握手。常见的诱因有几个调试服务进程没有启动或者已经崩溃。先用任务管理器或命令行确认端口 57436 是否有进程监听。目标机 VM 的网络栈卡死。这种时候重启调试服务或者把整个 VM 重新启动多半能恢复。防火墙拦截了回环端口。有些安全软件会连 127.0.0.1 都拦需要把调试器进程加入白名单。项目工程里的目标配置文件指向了错误的 transport 类型。报错里写着transport: soc说明调试器已经按照 SoC 调试链路来走但如果实际用的是 QEMU 模拟器配置应该是transport: qemu或类似模式配置不匹配就会出现握手失败。排查顺序我一般是从内向外先看端口监听再看调试服务日志最后看工程文件里 target configuration 的设置。不要一上来就重装软件十次里有八次是配置或者服务状态问题。那次会议上刚好有个演示环节也发生了类似报错现场工程师很坦诚地说“这是工具链和虚拟环境之间的老问题了”反而让我觉得这种问题不是我不会用而是生态本身还在演进。5. 算法落地中的 SoC 计算问题EKF 与容量校正5.1 电池 SOC 估算里的 EKF 为什么比安时积分靠谱SoC 这个词在硬件语境下是 System-on-Chip但在电池管理领域SoC 是 State of Charge也就是剩余电量。两边经常混在同一个项目里尤其是无人机、机器人这种设备主控是 SoC 芯片电池管理系统也在估算电量。搜索热词里那句“ekf考虑容量校正soc”说的就是电池领域的扩展卡尔曼滤波。安时积分是大家最容易想到的方法测电流乘时间累加电量。但问题在于电流传感器有偏置误差时间一长误差就积累必须要定期校正。普通卡尔曼滤波适合线性系统电池的等效电路模型在 SOC 和 OCV开路电压之间是一条非线性曲线所以要用 EKF把状态方程和观测方程做一阶线性化。EKF 在每一拍推算当前 SOC 和极化电压用电池端电压的实测值做校正可以把估算误差控制在几个百分点内。在 SoC 上实现 EKF不能把它当成一个简单数学函数。EKF 的核心是雅可比矩阵更新每一步要算矩阵乘法和求逆如果直接拿浮点矩阵库跑在低功耗 MCU 上会很吃力。需要根据电池模型复杂度做定点化处理大部分增益矩阵的元素范围是有限的可以选择合适的 Q 格式来避免除法。还要注意设定过程的协方差初值初值设得太大滤波收敛慢设得太小校正力度不足会出现 SOC 输出一直跟踪不上真实值的情况。5.2 在 SoC 上跑 EKF 的资源预算如果你要在主控 SoC 上同时跑控制算法、通信协议和电池 EKF就得提前算资源账。以双核 Cortex-A 加 FPGA 的 SoC 平台为例我通常这样分配实时控制跑在硬核实时核或 FPGA 状态机里电池 EKF 跑在应用核的一个 20ms 周期任务里通信协议栈跑在另一个核或者独立内存空间。EKF 的计算量取决于状态维数。一个常见的二阶 RC 模型状态变量是 SOC、R1C1 极化电压、R2C2 极化电压再加容量校正项大约 4 到 5 维。每一轮更新的矩阵规模在 5x5 左右浮点乘法次数约几千次在 1GHz 应用核上完全不是问题。真正的问题是缓存和中断冲突如果 EKF 任务和 DMA 中断抢 CPU会导致大量上下文切换执行周期抖动变大滤波性能下降。建议把 EKF 任务的优先级设成中等并且给它分配独占的定时器触发避免和硬件中断纠缠。容量校正这一项值得单独说。电池老化后实际容量会下降安时积分只基于标称容量算很容易在后期高估 SOC。EKF 里把容量作为状态变量进行扩展可以从充放电曲线中缓慢校正容量值。但容量校正的时间常数很长滤波器容易变得迟钝。我的做法是设置一个容量变化率阈值只有连续多次估计保持同一趋势时才更新容量值避免单次噪声干扰造成误校。5.3 无人机遥控器 MCUSoC 的通道数分配思路无人机遥控器是 SoC 应用的一个典型场景而且热词里正好有“无人机遥控器mcu和soc通道数”。遥控器内部经常是 MCU 和 SoC 并用MCU 负责实时摇杆采集、拨杆开关和物理按键SoC 负责图传、遥测、屏幕显示和网络通信。两边的通道数怎么分配直接决定遥控链路的表现。我见过的新手做法是把所有摇杆和按键通道全部接到 MCU再让 MCU 通过 SPI 把数据发给 SoC。这个方案的问题在于MCU 和 SoC 之间的通信延迟如果不稳定遥控指令的端到端时延就会跳动。更合理的方式是MCU 只负责最关键的摇杆通道通常 4 到 6 通道通过硬件定时器直接编码成 PPM 或 SBUS 信号输出给射频模块保证链路的最低延迟其余辅助通道旋钮、按钮、模式切换通过 SoC 转发允许几十毫秒的延迟。通道数并不是越多越好。很多高端遥控器宣称 16 通道、18 通道但实际上绝大多数用户在飞行中只依赖 4 个主要摇杆通道其余通道都是辅助功能。通道多了射频帧变长在 2.4GHz 频段容易撞包。所以选 SoC 和 MCU 的边界时要把实时通道放在 MCU 侧把需要计算和协议处理的通道放在 SoC 侧这才是比较合理的分工。6. 国产 SoC 生态与驱动实战海光芯片组6.1 海光 SoC 芯片组驱动安装的顺序问题这两年国产 SoC 平台用得越来越多朋友圈里聊“海光soc芯片组驱动”的频率也上来了。海光本身是 x86 架构的处理器在服务器和工作站场景里很常见对大家来说最直接的问题就是装系统时的驱动顺序。很多人以为直接把 Linux 发行版光盘塞进去装完就能用结果发现网络、显卡、USB 控制器驱动不全设备管理器里一堆感叹号。芯片组驱动的安装顺序我自己总结了一套经验先装主板芯片组驱动再装 PCIe 控制器和 IOMMU 相关驱动接着是网络驱动和显卡驱动最后才装安全启动和电源管理组件。这个顺序不能乱因为芯片组驱动会建立系统总线的基础信息后面的驱动要依赖它来识别设备和分配资源。如果先装显卡驱动再回头补芯片组驱动容易在重启后出现资源冲突表现为部分 PCIe 设备消失或者带宽异常。Linux 下更常见的坑是 IOMMU 没开或者配置错。海光平台如果想跑设备直通或者大规模 DMA 应用必须在内核参数里正确配置 IOMMU否则某些 PCIe 设备会报 DMA 错误系统日志里直接刷DMAR: [FATAL]。解决方法是确认 BIOS 里开启 SVM 或 AMD IOMMU 选项并在 grub 启动参数里添加对应的iommupt或amd_iommuon配置然后重新生成 grub 配置。驱动顺序和固件配置这两件事看起来像是运维杂活但在 SoC 项目里往往决定后续软件栈能否稳定跑满性能。6.2 从 2014 年到现在SoC 生态的最大变化如果让我给 2014 年那次会议和现在做一个对比最大的变化不是芯片性能翻了多少倍而是软件和工具链的复杂度超过了硬件本身。当年我们做 Zynq还在为“裸机还是 Linux”争论现在大家张口就是完整启动链、虚拟化、设备树、电源域管理、安全启动。软件栈的深度已经让 SoC 开发从硬件工程师的专属领域变成一个需要软硬结合的系统工程。另一个变化是领域专用 SoC 越来越多。RFSoC 把射频和数字合成到一起Versal 把自适应算力做成可配置资源电池管理 SoC 把 EKF 这类算法做成硬核 IP这些都说明 SoC 的边界正在从“通用计算”向“场景计算”扩展。2014 年你很难想象一个 SoC 内部既要管理电源纹波又要跑 EKF 容量校正还要处理射频直采的数据。现在这些都已经成为日常工作的一部分。那次会议结束后我养成了一个习惯拿到任何新的 SoC 板卡先不急着写应用而是花半天时间做完整的 bring-up 检查。从启动链路的每一级固件开始到设备树与实际硬件做交叉核对再到关键电源轨的纹波测量最后才让算法和应用代码跑起来。这个流程看起来很慢但它帮我避开了无数次“代码没问题但板子不工作”的尴尬。SoC 的每一次进步都是用更多细节堆出来的那些细节恰恰是会议议程里不会写成大字标语、但值得你花一张早鸟票去慢慢挖掘的东西。
返回列表