1. BSP性能调优概述

做嵌入式系统这么多年,我越来越觉得BSP(板级支持包)就像一座桥梁。它一头连着硬件,一头连着操作系统。说白了,BSP就是让Linux内核能听懂你的CPU、内存、外设都在说什么。

很多刚入行的工程师觉得BSP就是写写驱动、改改设备树。嗯,这话对了一半。真正到了产品阶段,你会发现BSP的核心任务其实是——性能调优。硬件选型定了,芯片频率锁了,剩下的性能空间,全靠BSP来榨。

1.1 BSP在嵌入式系统中的角色

先聊聊BSP到底在系统里扮演什么角色。我个人习惯把它拆成三层来看:

  • 硬件抽象层:把CPU、中断控制器、定时器这些硬件细节封装起来。内核上层不用管你用的是Cortex-A72还是RISC-V。
  • 驱动框架层:提供标准化的设备驱动接口。比如网络用NAPI,存储用块设备层,显示用DRM/KMS。
  • 系统初始化层:从Bootloader跳转到内核,到setup_arch()完成,再到各个子系统初始化。这一步出问题,后面全白搭。

我在项目中遇到过一件事:某款AI摄像头产品,同样的芯片,A团队做的BSP跑模型推理只有12fps,B团队优化后跑到了30fps。差别在哪?就是BSP对缓存一致性、DMA通道、中断亲和性的处理方式完全不同。

核心观点:BSP不是"能跑就行"的胶水代码。它是整个嵌入式系统的性能地基。地基没打好,上层应用再怎么优化也白费。

1.2 性能调优的核心指标

调优之前,你得先知道"好"的标准是什么。我一般盯着三个指标看:

指标 定义 典型场景 我常用的测量工具
延迟 从事件发生到系统响应的时间差 中断响应、DMA传输、任务调度 ftrace、perf、cyclictest
吞吐量 单位时间内系统处理的数据量 网络收包、磁盘读写、编解码 iperf、dd、netperf
CPU占用率 CPU用于处理有效任务的时间占比 中断负载、内核线程、用户态进程 top、htop、perf stat

这三个指标其实是互相牵制的。你想想看,为了降低延迟,你把中断频率调高了,结果CPU一直在处理中断,吞吐量反而下来了。这就是典型的"按下葫芦浮起瓢"。

我的经验:调优前先定好"首要指标"。比如实时控制系统,延迟是第一位的,CPU占用率可以放宽。数据采集设备,吞吐量优先,延迟只要在可接受范围就行。

1.3 调优方法论与工作流程

调优不是拍脑袋乱改参数。我总结了一套流程,这些年一直在用:

  1. 建立基线:先跑一遍默认配置,记录所有关键指标。没有基线,你根本不知道改完是变好了还是变差了。
  2. 定位瓶颈:用perf、ftrace、火焰图这些工具,找到真正的热点在哪。我曾经见过有人花了两周优化网络驱动,结果瓶颈在内存分配器上——方向错了,全白干。
  3. 制定方案:针对瓶颈,列出可能的优化手段。比如中断合并、DMA缓冲对齐、缓存预取、内存池化等。
  4. 单变量实验:一次只改一个参数。改完重新测量,记录变化。多个参数一起改,出了问题你根本不知道是谁的锅。
  5. 验证回归:优化完一个点,要确保其他指标没有恶化。延迟降了,但吞吐量掉了一半,这种优化不能上线。
  6. 固化配置:把最终调优参数写进设备树、内核配置或驱动代码里。形成文档,方便后续维护。

避坑指南:我曾经在一个项目中,为了追求极致的网络吞吐量,把NAPI的轮询预算调得特别大。结果网络性能确实上去了,但视频编码线程因为长时间得不到调度,导致画面卡顿。这就是典型的"局部最优,全局次优"。调优一定要看全系统。

下面这张图是我自己画的工作流程,你可以参考一下:

BSP性能调优工作流程 BSP性能调优工作流程 ① 建立基线 ② 定位瓶颈 ③ 制定方案 ④ 单变量实验 ⑤ 验证回归 ⑥ 固化配置 不达标则回退 关键原则 • 一次只改一个参数 • 每次改动都要记录 • 关注全局而非局部

这个流程看起来简单,但真正执行起来,最难的其实是第二步——定位瓶颈。我见过太多人拿着perf跑一遍,看到某个函数占用CPU高,就一头扎进去优化。结果优化完发现,那个函数之所以占用高,是因为它在等某个锁,而锁的持有者才是真正的瓶颈。

所以我的建议是:先看全局,再抓局部。用火焰图看全系统的CPU分布,用ftrace看内核事件的时间线,用perf stat看硬件计数器。把这些信息综合起来,才能找到真正的"七寸"。

一句话总结:BSP性能调优不是玄学,是一套有章可循的工程方法。掌握好核心指标,走对工作流程,你就能从"代码能跑"进化到"系统能打"。