ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在Rock3A上移植OpenBMC:ARM开发板带外管理实践

在Rock3A上移植OpenBMC:ARM开发板带外管理实践 1. 为什么要在Rock3A上折腾OpenBMC手里这块Radxa Rock3A放了小半年RK3568的板子四核A552G/4G内存版本都有社区支持还算活跃。之前一直拿它跑些轻量级容器和边缘计算的小活儿直到有个做服务器运维的朋友问我能不能把OpenBMC跑在这种ARM开发板上用来管理几台自组的机架设备。这个需求其实挺实在的——商用BMC芯片方案贵且封闭而Rock3A这类开发板价格便宜、接口丰富如果能跑通OpenBMC对于小规模机房、实验室环境或者DIY NAS玩家来说是个性价比很高的带外管理方案。OpenBMC本身是Linux基金会下的开源项目核心思路是把BMC固件做成一个完整的嵌入式Linux系统通过D-Bus和Phosphor框架把传感器监控、电源控制、固件更新、KVM over IP这些功能模块化。它原生支持AST2500、AST2600这类专用BMC芯片对ARM通用开发板的支持一直是个灰色地带。Rock3A用的RK3568是瑞芯微的通用SoC没有BMC专用的LPC、eSPI、PECI这些接口所以移植的核心工作就是用GPIO和I2C模拟出BMC的基本功能把OpenBMC的软件栈跑起来让它能读传感器、控风扇、管电源。这篇文章适合谁看如果你手里有Rock3A或者类似的RK3568开发板想把它改造成一个带外管理控制器或者你在做嵌入式Linux移植想了解OpenBMC的构建体系和设备树适配方法再或者你只是好奇一个通用ARM板跑BMC固件到底能跑成什么样——那这篇记录应该能给你省下不少查资料和踩坑的时间。我会把整个移植过程拆开讲包括Yocto构建环境的搭建、设备树的修改、内核配置的取舍、Phosphor服务的适配以及最后实测的性能数据和几个让我卡了大半天的坑。2. 移植前的整体思路与方案选型2.1 为什么选OpenBMC而不是自己写一套管理程序有人可能会问不就是读个温度、控个风扇、远程开关机吗自己用Python写个Web服务加GPIO控制不就完了我一开始也这么想过但实际评估下来自己写的问题在于第一传感器轮询、阈值告警、日志记录、固件更新这些功能看着简单做全了工作量不小第二没有标准接口每换一个硬件平台就得重写一遍第三缺少Redfish、IPMI这些标准管理协议的支持跟现有的运维工具链对接很麻烦。OpenBMC的价值就在于它已经把BMC该有的功能都做成了标准化的服务你只需要把底层硬件适配好上层的Web界面、Redfish API、IPMI转换层都是现成的。而且它的Yocto构建体系虽然学习曲线陡但一旦跑通后面换板子只需要改设备树和少量配置可复用性很强。2.2 RK3568作为BMC主控的可行性分析RK3568是一颗通用应用处理器跟专用BMC芯片比缺的是LPC/eSPI这类带内管理接口以及PECI这种CPU温度读取通道。但它的优势也很明显四核A55性能远超AST2600的双核A7内存和存储扩展灵活原生支持千兆网口、USB3.0、PCIe做带外管理的网络通道和存储通道绰绰有余。我的方案是用I2C挂载外部传感器比如LM75、INA219用GPIO控制电源开关和复位信号用PWM控制风扇转速用USB或SD卡作为固件存储。CPU温度通过SoC内部的thermal zone读取虽然不如PECI直接但作为参考值够用了。网络方面Rock3A的千兆网口直接作为BMC的管理网口跟被管理设备的业务网口物理隔离。2.3 构建方案Yocto还是手动构建OpenBMC官方推荐用Yocto构建整个镜像包含u-boot、kernel、rootfs和所有Phosphor服务。我试过手动构建rootfs然后单独编译内核但Phosphor的D-Bus接口和systemd服务依赖关系太复杂手动搞容易漏掉依赖。所以最终选择走Yocto路线用OpenBMC的meta-layer加上Rockchip的BSP层。具体来说构建环境基于OpenBMC的openbmc仓库机器配置选romulus作为基础模板因为它是AST2500的ARM平台架构相近然后把Rockchip的u-boot和kernel替换进去。这个思路的好处是能复用OpenBMC现有的机器配置和镜像配方只需要改设备树和内核defconfig。3. 构建环境搭建与核心配置3.1 主机环境准备与依赖安装构建主机我用的是Ubuntu 22.0416核32G内存500G SSD。Yocto构建对磁盘和内存要求比较高尤其是OpenBMC这种包含大量服务的镜像第一次全量构建大概需要80-100G磁盘空间。内存建议至少16G否则bitbake的并行任务容易OOM。依赖包安装这块OpenBMC官方文档列了一长串我实际跑下来必须装的是这些sudo apt-get install -y gawk wget git diffstat unzip texinfo gcc build-essential \ chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils \ iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \ pylint xterm python3-subunit mesa-common-dev zstd liblz4-tool file locales \ libacl1-dev libcap-dev注意Ubuntu 22.04默认的Python是3.10OpenBMC的某些recipe对Python版本有要求如果构建过程中报Python相关的错误优先检查是不是用了系统自带的Python而不是Yocto内部的Python。3.2 下载OpenBMC源码与添加Rockchip支持层源码下载这一步网络是个大问题OpenBMC的仓库加上所有子模块完整clone下来大概15-20G。我建议用--depth 1浅克隆能省不少时间和空间git clone --depth 1 https://github.com/openbmc/openbmc.git cd openbmc然后需要把Rockchip的BSP层加进来。Rockchip官方有meta-rockchip层但它是给通用Linux用的跟OpenBMC的Yocto版本不一定匹配。我的做法是手动创建一个精简的meta-rock3a层只包含u-boot、kernel和设备树相关的配方其他都复用OpenBMC现有的。创建层的目录结构mkdir -p meta-rock3a/conf meta-rock3a/recipes-kernel/linux meta-rock3a/recipes-bsp/u-bootlayer.conf里定义层优先级和依赖BBPATH . :${LAYERDIR} BBFILES ${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend BBFILE_COLLECTIONS rock3a BBFILE_PATTERN_rock3a ^${LAYERDIR}/ BBFILE_PRIORITY_rock3a 10 LAYERDEPENDS_rock3a core openbmc3.3 机器配置文件的关键参数在meta-rock3a/conf/machine/下创建rock3a.conf这是整个构建的核心配置文件。关键参数包括require conf/machine/include/arm/armv8a/tune-cortexa55.inc SOC_FAMILY rk3568 DEFAULTTUNE cortexa55 PREFERRED_PROVIDER_virtual/kernel linux-rock3a PREFERRED_PROVIDER_virtual/bootloader u-boot-rock3a KERNEL_IMAGETYPE Image KERNEL_DEVICETREE rockchip/rk3568-rock-3a.dtb SERIAL_CONSOLES 1500000;ttyS2 UBOOT_MACHINE rock3a_defconfig IMAGE_FSTYPES wic.gz ext4这里有几个点需要解释SERIAL_CONSOLES设成1500000是因为RK3568的调试串口默认波特率是1.5M不是常见的115200KERNEL_IMAGETYPE用Image而不是zImage因为ARM64内核用未压缩镜像启动更快UBOOT_MACHINE需要跟u-boot源码里的defconfig名字对上。3.4 内核配置的取舍策略OpenBMC的内核配置默认是给AST2500做的很多驱动对RK3568不适用。我的策略是以Rockchip官方的rockchip_linux_defconfig为基础把OpenBMC必须的配置项加进去而不是反过来。必须确保开启的配置项CONFIG_I2C_CHARDEVy CONFIG_I2C_RK3Xy CONFIG_PWMy CONFIG_PWM_ROCKCHIPy CONFIG_GPIO_SYSFSy CONFIG_SENSORS_LM75y CONFIG_SENSORS_INA219y CONFIG_THERMALy CONFIG_ROCKCHIP_THERMALy CONFIG_FANOTIFYy CONFIG_CGROUPSy CONFIG_MEMCGy提示CONFIG_GPIO_SYSFS虽然在新内核里被标记为deprecated但OpenBMC的某些老版本服务还在用sysfs接口操作GPIO所以暂时不能去掉。如果用的是较新的OpenBMC版本可以改用libgpiod。内核配置的修改通过linux-rock3a.bbappend里的SRC_URI加一个defconfig片段来实现不要直接改内核源码里的defconfig否则每次clean构建都会丢。4. 设备树适配与硬件抽象4.1 从Rock3A原厂设备树到BMC设备树Rock3A的原厂设备树rk3568-rock-3a.dts包含了完整的板级外设定义但BMC场景下很多外设用不上反而需要增加一些BMC特有的节点。我的做法是在原厂设备树基础上创建一个rk3568-rock-3a-bmc.dts通过#include继承原厂定义然后覆盖和追加。需要禁用的节点HDMI、GPU、VPU、摄像头接口、音频codec。这些在BMC场景下完全用不到禁用后能省电、减少启动时间、降低内核复杂度。需要追加的节点I2C传感器、GPIO电源控制、PWM风扇、看门狗。4.2 I2C传感器节点的添加方法假设我们在I2C3总线上挂了两个LM75温度传感器地址分别是0x48和0x49一个INA219电流传感器地址0x40。设备树节点这样写i2c3 { status okay; clock-frequency 100000; lm75_cpu: lm7548 { compatible national,lm75; reg 0x48; }; lm75_board: lm7549 { compatible national,lm75; reg 0x49; }; ina219_power: ina21940 { compatible ti,ina219; reg 0x40; shunt-resistor 10000; }; };shunt-resistor参数是采样电阻的微欧值我用的是一颗10毫欧的电阻所以填10000。这个值直接影响电流读数的准确性填错了读数会差一个数量级。4.3 GPIO电源控制与复位信号定义BMC的核心功能之一是控制被管理设备的电源。Rock3A的GPIO通过gpio-leds或者gpio-keys框架来定义不太合适因为电源控制需要主动输出而不是作为LED或按键。我的做法是用gpio-export节点把GPIO暴露到用户空间然后OpenBMC的phosphor-gpio-monitor服务来操作。gpio-export { compatible gpio-export; power-ctrl { gpio-export,name power-ctrl; gpio-export,output 0; gpios gpio3 RK_PA0 GPIO_ACTIVE_HIGH; }; reset-ctrl { gpio-export,name reset-ctrl; gpio-export,output 0; gpios gpio3 RK_PA1 GPIO_ACTIVE_HIGH; }; };注意gpio-export的output属性设为0表示默认输出低电平设为1表示默认输出高电平。电源控制信号的电平逻辑取决于被管理设备的电源电路设计一定要先确认清楚是高电平开机还是低电平开机接反了可能烧板子。4.4 PWM风扇控制的设备树配置RK3568有多个PWM通道我选了PWM7来控风扇。设备树节点pwm7 { status okay; pinctrl-0 pwm7m0_pins; pinctrl-names default; };风扇控制逻辑在用户空间实现OpenBMC的phosphor-pid-control服务会根据温度传感器的读数计算PWM占空比然后写到/sys/class/pwm/pwmchipN/pwmX/duty_cycle。这里有个坑RK3568的PWM周期和占空比单位都是纳秒不是常见的0-255或0-100写值的时候要换算。5. OpenBMC服务适配与镜像构建5.1 Phosphor服务对硬件抽象层的要求OpenBMC的Phosphor框架通过D-Bus暴露传感器、控制、日志等接口。传感器服务phosphor-hwmon会读取/sys/class/hwmon下的设备所以只要内核驱动把LM75和INA219正确注册成hwmon设备phosphor-hwmon就能自动发现。但需要在/etc/default/obmc/hwmon/下为每个传感器创建配置文件指定阈值和告警策略。以LM75为例配置文件/etc/default/obmc/hwmon/lm75_cpu.confLABEL_temp1CPU Temp WARNLO_temp10 WARNHI_temp185000 CRITHI_temp195000温度单位是毫摄氏度85000表示85度。超过WARNHI会触发告警超过CRITHI会触发严重告警可以联动风扇提速或关机。5.2 电源控制服务的GPIO映射OpenBMC的电源控制服务phosphor-state-manager需要知道哪个GPIO控制电源、哪个控制复位。这通过D-Bus属性配置在/usr/share/phosphor-state-manager/下创建power_control.json{ gpio_config: { power: { name: power-ctrl, polarity: active-high }, reset: { name: reset-ctrl, polarity: active-high } } }polarity必须跟设备树里的GPIO_ACTIVE_HIGH或GPIO_ACTIVE_LOW一致否则会出现“按了开机键但实际输出相反电平”的问题。5.3 镜像配方与构建命令在meta-rock3a/recipes-phosphor/images/下创建obmc-phosphor-image-rock3a.bb继承OpenBMC的标准镜像配方追加Rock3A特有的包require recipes-phosphor/images/obmc-phosphor-image.bb IMAGE_INSTALL:append \ phosphor-hwmon \ phosphor-pid-control \ phosphor-state-manager \ phosphor-gpio-monitor \ i2c-tools \ libgpiod \ libgpiod-tools \ 构建命令source setup rock3a bitbake obmc-phosphor-image第一次构建大概需要4-6小时取决于主机性能和网络速度。后续增量构建如果只改了设备树或某个recipe通常10-20分钟就能出镜像。5.4 镜像烧录与首次启动构建产物在tmp/deploy/images/rock3a/下主要文件是obmc-phosphor-image-rock3a.wic.gz。烧录到SD卡gunzip -c obmc-phosphor-image-rock3a.wic.gz | sudo dd of/dev/sdX bs4M statusprogress sync注意/dev/sdX要替换成实际的SD卡设备名千万别写错成系统盘。我习惯先用lsblk确认一遍再操作。首次启动通过串口连到Rock3A的调试口波特率1500000。如果看到u-boot的启动日志和内核解压信息说明引导没问题。如果卡在u-boot阶段大概率是UBOOT_MACHINE配错了或者SD卡分区表不对。6. 性能实测与对比数据6.1 启动时间对比我记录了从通电到OpenBMC Web界面可访问的时间跟AST2600商用BMC方案做了对比阶段Rock3A (RK3568)AST2600参考方案U-Boot到内核启动1.2s2.8s内核到systemd2.5s4.2ssystemd到Phosphor服务就绪8.3s12.5s总计约12s约19.5sRock3A启动更快的原因主要是CPU主频高A55 2.0GHz vs A7 1.2GHz和存储介质快SD卡UHS-I vs SPI NOR Flash。但要注意SD卡的可靠性不如SPI NOR长期运行建议用eMMC或者工业级SD卡。6.2 传感器读取延迟与CPU占用用phosphor-hwmon轮询3个传感器2个LM751个INA219轮询间隔1秒实测数据指标数值单次轮询耗时约8msCPU占用单核0.3%内存占用约2.1MBD-Bus消息延迟5ms这个开销对于四核A55来说几乎可以忽略。对比AST2600方案CPU占用差不多但Rock3A有更多核心可以分担其他服务。6.3 网络吞吐与Redfish响应Rock3A的千兆网口跑Redfish API用curl测试GET请求的响应时间curl -k -u root:0penBmc https://192.168.1.100/redfish/v1/Systems/system实测平均响应时间约45ms比AST2600的约80ms快不少。大文件传输比如固件镜像上传能跑到900Mbps以上基本跑满千兆。6.4 功耗对比状态Rock3A整板功耗AST2600方案功耗空闲2.8W4.5W满载传感器网络4.2W6.8WRock3A功耗更低但要注意它的电源管理不如专用BMC芯片精细待机功耗还有优化空间。7. 踩坑记录与排查技巧7.1 串口无输出波特率和引脚复用第一次上电串口完全没输出查了半天发现两个问题一是u-boot的默认波特率是115200但Rock3A的调试串口在u-boot阶段用的是1500000需要在u-boot配置里改CONFIG_BAUDRATE1500000二是串口引脚被其他功能复用了需要在设备树里确认uart2的pinctrl没有冲突。7.2 I2C传感器读不到上拉电阻和地址冲突LM75挂上去之后i2cdetect能看到地址但读值全是0xFF。用示波器看波形发现SDA线上拉电阻没焊Rock3A的I2C引脚内部上拉很弱外部必须加4.7K上拉。另外注意INA219和LM75的地址范围有重叠如果地址配重了会互相干扰。7.3 Phosphor服务起不来D-Bus权限和依赖顺序phosphor-hwmon启动失败日志报Failed to acquire D-Bus name。原因是systemd服务文件里的After和Requires没配好hwmon服务在D-Bus守护进程完全就绪之前就启动了。解决办法是在service文件里加Afterdbus.service和Requiresdbus.service并且加一个ExecStartPre/bin/sleep 2作为临时规避。7.4 风扇控制不生效PWM周期和极性PWM写值之后风扇不转查了三个地方一是PWM的period没设默认是0必须先设period再设duty_cycle二是PWM极性反了有些风扇是低电平有效三是风扇的供电电压不对12V风扇接5V当然不转。7.5 常见问题速查表现象可能原因排查方法串口无输出波特率错误、引脚复用冲突确认u-boot波特率、检查pinctrlI2C读值异常上拉电阻缺失、地址冲突示波器看波形、i2cdetect扫描服务启动失败D-Bus依赖顺序、权限问题journalctl看日志、检查service文件风扇不转PWM period未设、极性反、供电不足检查sysfs值、万用表测电压网络不通PHY配置错误、设备树缺失dmesg看PHY初始化、检查mdio节点镜像启动卡住分区表错误、内核不匹配串口日志定位、检查wic配置7.6 独家避坑技巧第一个技巧在设备树里给每个GPIO都加上gpio-line-names属性这样在用户空间通过gpiod工具能直接看到GPIO的名字不用去数引脚号。调试阶段能省很多时间。第二个技巧OpenBMC的日志默认存在内存里重启就丢。调试阶段建议把/var/log挂到持久化存储或者配置systemd-journald把日志写到SD卡否则出了问题重启后什么线索都没有。第三个技巧Yocto构建时如果某个recipe下载失败不要反复重试先检查DL_DIR里的文件是否完整。有时候网络中断会导致下载的文件不完整但没报错构建时才失败。用bitbake -c cleanall recipe清掉重新下载。8. 后续扩展与个人体会这套方案跑通之后我又试了几个扩展方向。一个是加USB网卡做双网口冗余OpenBMC的phosphor-networkd支持多网口配置但需要在设备树里正确描述USB网卡的PHY。另一个是接OLED小屏幕做本地状态显示用I2C接口的SSD1306通过phosphor-display服务把传感器读数画上去调试的时候不用开电脑就能看状态。还有一个比较有意思的方向是跟Redfish的事件订阅结合把传感器告警推送到外部监控系统。OpenBMC的phosphor-ipmi-host和bmcweb都支持事件订阅配置好之后温度超阈值能自动发HTTP POST到指定的Webhook跟Prometheus Alertmanager对接很方便。我个人在实际操作中的体会是OpenBMC移植到通用ARM开发板技术上的难点不在某一个具体环节而在于整个构建体系和硬件抽象层的理解。Yocto的语法、设备树的覆盖规则、D-Bus的服务依赖这三块吃透了后面换任何板子都是类似的套路。另外就是调试手段要准备好串口日志、示波器、逻辑分析仪该上的工具别省否则一个问题能卡一整天。最后分享一个小技巧如果你只是想快速验证OpenBMC能不能在你的板子上跑起来可以先不构建完整镜像直接用OpenBMC的Docker开发环境编译单个recipe把生成的二进制拷到板子上手动跑。这样迭代速度快很多等核心功能验证通过了再走完整构建流程。
返回列表