Firefly集群服务器是一款高密度ARM核心板卡的集群服务器。服务器采用机架式服务器规格设计,核心板卡基于Rockchip芯片平台。通过Firefly的创新设计和软件支持,使得集群服务器在云手机、边缘计算等多领域具有良好的适应性。Firefly集群服务器经过多个软硬件版本迭代,现已经具有完善合理的软硬件系统支持,并且具有以下特色:
高密度核心:
R1版集群服务器为1U规格,支持集成11个独立核心板卡。
R2版集群服务器为2U规格,支持集成72个独立板卡。
核心板卡可配置
根据业务场景的需求,集群服务器的核心板卡可以选择不同的规格。并且也支持不同规格板卡混插。如云手机、AI运算、区块链运算等,都可以选用不同规格的核心板卡。
核心板软件系统独立
集群服务器各个核心板卡可独立运行Android/Linux 操作系统。单个核心板故障不会导致整个服务器宕机。
BMC可视化管理系统
通过集群服务器的BMC管理单元,可以实现用户在web浏览器对核心板卡的监测、配置、系统更新等操作。
热插拔设计
集群服务器的电源单元、子核心板单元、网络单元、温控单元、扩展存储单元均采用热插拔设计,可以有效降低服务器的部署和维护工作。
冗余设计
集群服务器的电源管理单元和网络管理单元采用冗余设计,可以应对部分电源和网络的突发故障。
温控设计
集群服务器集成温控单元,通过监测服务器内环境温度和核心温度,可以有效调节散热风扇工作状态,优化服务器的整体性能和稳定性。
型 号 | Cluster Server R1 | Cluster Server R2 |
---|---|---|
核心板卡数 | 11 | 72 (热插拔设计) |
构 架 | ARM架构 | ARM架构 |
操作系统 | 支持Android、Ubuntu、Linux操作系统 | 支持Android、Ubuntu、Linux操作系统 |
网 络 | 1GE千兆RJ45网口4个其中:主核心板网口1个,普通网口3个 | 双网卡冗余设计,单网卡集成:千兆网口(RJ45)×2、万兆网口(SFP+)×2BMC网络接口 |
4G | 4G/LTE/5G网络(可选配) | 不支持 |
显 示 | 1×Mini HDMI 2.0,4K@60Hz(控制主板显示) | 1×Mini HDMI 2.0,4K@60Hz(控制主板显示) |
扩展存储 | 3.5寸STAT硬盘 | 3.5寸STAT硬盘 / SD卡 |
USB | 2个USB2.0 HOST1 个 Type-C(处理器核心板调试用) | 1 × USB3.0 HOST |
电 源 | 300W AC电源(输入:100V AC~240V AC) | 双路冗余电源设计 :AC 100~240V 50/60Hz,1300W / 800W 可选 |
散 热 | 散热片 +5个高速散热风扇 | 散热片 + 2组风扇模组: 风扇模组1(3×2冗余风扇设计)、风扇模组2(2×2冗余风扇设计) |
UID | 无 | UID按键×1 |
硬件看门狗 | 有 | 有 |
型 号 | Cluster Server R1 | Cluster Server R2 |
---|---|---|
节点数 | 一体化1U服务器 | 9个刀片节点 每个节点都能配置8个处理器核心板 节点9可用于安装2个3.5寸SATA/SSD硬盘 |
核心数 | 最高可配置11个处理器核心板 | 最高可配72个处理器核心板 |
核心板 | RK3399(AI)核心板(Core-3399-JD4) RK3328核心板(Core-3328-JD4) RK1808(AI)核心板(Core-1808-JD4) RK3588核心板(Core-3588SJD4) |
RK3399(AI)核心板(Core-3399-JD4) RK3328核心板(Core-3328-JD4) RK1808(AI)核心板(Core-1808-JD4) RK3588核心板(Core-3588SJD4) |
内 存 | 1GB / 2GB / 4GB | 1GB / 2GB / 4GB |
存 储 | eMMC 3.5英寸硬盘 1个SATA/SSD硬盘 |
eMMC 3.5英寸SATA/SSD硬盘位x2(节点9) SD卡 x1 |
说明: Firefly后期会持续推出更高性能,更大内存的的核心子板,支持8 / 16G内存
型 号 | Cluster Server R1 | Cluster Server R2 |
---|---|---|
尺 寸 | 标准1U机架式:490mm x 390mm x 44.4mm | 标准2U服务器机箱:580mm x 434mm x 88.8mm |
重 量 | 服务器主机:5.8kg 包装总重:7.2 kg | 包装总重量:29 kg |
型 号 | Cluster Server R1 | Cluster Server R2 |
---|---|---|
工作温度 | 0ºC - 40ºC | 0ºC - 50ºC |
工作湿度 | 8%RH~95%RH | 10%RH~80%RH |
集群服务器 Cluster Server R2 (9刀)
《旧款集群服务器 Cluster Server R2 (6刀 不维护)实物图》
1. POWER LED x2 电源状态指示灯:分别对应主机左右(正面图)2个电源,电源正常为绿色,电源异常或缺失则相应位置的LED为红色。
2. BMC LED 主板状态指示灯:主机main主板正常进入系统后亮起。
3. FAN LED x2 风扇状态指示灯:风扇正常为绿色,风扇转速异常或没接入风扇模块则相应位置的LED为红色,并响起蜂鸣器提示声。
4. UID LED UID指示灯: 按下UID按键(背面图的10号键)后常亮,便于机房维护人员使用。
5. NET LED x2 交换机状态显示灯,正常为绿色,交换机异常或没有接入则相应位置的LED为红色。
6. POWER KEY 电源按键:按下按键不松开,听到蜂鸣器提示声,等提示声消失后立即松开按键(持续时间为3s)。详情可查看开关机操作。
7. RESTART KEY 复位按键: 按下复位键,main板强制重启。
正常开机: 在主机关机状态下,按下POWER KEY不松开,持续几秒。
正常关机: 在主机开机状态下,按下POWER KEY不松开,并听到蜂鸣器提示声,持续3s,主机确认关机状态后蜂鸣器提示声消失,立即松开按键。主机进行正常关机。
强制关机(一般情况下不建议使用): 在主机开机状态下,按下POWER KEY不松开,并听到蜂鸣器提示声,持续5s,主机强制断电。
实现正常关机的条件是main core安装的linux系统,并安装了firefly-sr-service-*.deb,出厂固件默认已安装。
BMC管理系统是一套运行集群服务器BMC管理单元上的软件系统,BMC管理单元是一块使用RK3399作为主控芯片的控制板(以下简称主板),主板运行Ubuntu 18.04系统,通过网络和USB接口与集群服务器内其它核心板(以下简称子板)进行数据交互,实现对集群服务器各个核心板卡的监测和管理。其软件栈的组成为:
node_exporter: 运行在主板和子板上,负责收集设备的监控数据。
Prometheus: 运行在主板上,负责收集和存储各个设备的监控数据。
Grafana: 运行在主板上,负责监控图表的集中显示。
该方案的优点是,由主板统一布署 node_exporter 到各个设备上(子板的操作系统可以是 Android 或 Ubuntu),以直观的图表方式显示各个子板的资源使用状况。
外接HDMI显示器:
通过集群服务器的HDMI接口接显示器,接入鼠标键盘,可以登入BMC管理单元Ubuntu系统,打开系统浏览器,在地址栏输入 http://127.0.0.1:3000 并回车即可访问,⽆需任何配置。
使用BMC扫描工具:
通过BMC扫描工具可获取同一局域网内所有的BMC管理系统IP地址,打开工具后会默认扫描一次局域网,也可通过刷新按钮 手动扫描,根据软件界面中呈现的BMC管理系统IP地址列表项,点击ACTIONS下相应的
图标即可打开外部浏览器并进入相应IP地址的BMC管理系统登录页面。
BMC系统初始用户名:admin 密码:admin,点击登录按钮,进⼊默认的设备列表页⾯。
登录后默认进入设备列表页面。任何时候需要访问设备列表页面,点击左边工具栏上的 图标即可进入:
这是集群服务器所有设备的列表,每个卡片代表一块设备。
设备列表页面的左上角,有两个下拉列表:
(1). 设备:可以过滤需要显示的设备,这在设备比较多的情况下很有用。
(2). 离线设备:仅供快速查看离线设备的列表。
往下看,这是服务器提供的外设接口图(仅R1 有此面板):4个网口,双层USB,HDMI,OTG,Sim Card,磁盘;
U:LAN 表示:上方黄色的LED灯的亮/灭对应着该设备的网络状态;
D:WORK 表示:下方绿色的LED灯的亮/灭对应着该设备的工作状态;
每个设备卡片,根据状态有不同的显示:
当设备可以通过 adb 访问,并进入正常的操作系统:
卡片顶部左边以绿色字样显示“设备可用”状态,后跟设备的当前操作系统,右边显示的是软件操作系统的版本和硬件版本(硬件版本仅 R2 有);
左边的图标表示核心板的 CPU 型号(CPU 核数和最高频率)、DDR 内存(4G) 和 eMMC 容量(32G);
“sub04”: 表示设备的 SUB 编号;
:点击该按钮进入 Shell 终端窗口;
:点击该按钮进入该设备的资源明细终端窗口;
:点击该按钮重置设备电源;
卡片右边第二行显示该设备的主网络接口的 IP 地址及连接速率,鼠标悬停时会显示所有网络接口地址和速率(目前仅主板有多个网络接口);
四个方块图分别显示 CPU、内存和磁盘的使用率,以及 CPU 的温度。
当设备处于离线状态,即设备由于物理移除、固件失效或操作系统异常等原因导致与主板的 usb 通讯失效时:
卡片顶部以橙色字样显示“设备不可用”状态;
:点击该按钮重置设备电源。
当设备处理维护状态,即设备处于系统升级模式(loader)、固件升级系统(netrecovery)、安卓急救模式(android_recovery)或 ADB 离线(android_offline),将会显示:
卡片顶部以黄色字样显示“设备维护”状态,后跟设备的明细状态。
设备信息均为空,维护状态下不采集监控数据。
:点击该按钮重置设备电源。
在设备列表或其它仪表盘页面中,点击最左上角的仪表盘名称:
可以查看更多的仪表盘:
目前有以下仪表盘:
设备概览
设备明细
CPU 频率与温度监控
在仪表盘页面中,右上角的工具条,可以选择浏览时段,以及多长间隔自动更新。下图就显示最近 6 小时的数据,并每 5 秒更新一次。
点击 按钮可手工刷新监控数据页面显示。
通过仪表盘列表,或点击左边工具栏上的 图标即可进入设备概览页面:
设备概览页面将所有设备的 CPU、内存、磁盘和网络这四项数据集中显示在一起:
鼠标悬停在曲线图上即可显示设备的明细数值。
右上的“告警列表”,当 CPU、内存和磁盘超过红色警戒线一段时间,即触发告警动作,例如发送邮件等(此项功能需配置相关参数,待加说明)。
右下的“设备列表”,列出所有在线设备的结点名称和 IP 地址,方便查看。鼠标点击即可查看该设备的设备明细页面。
有以下几种方法可以进入设备明细页面:
设备列表页面中点击设备卡上的 按钮;
设备概览页面中点击右边设备列表上的表格项;
通过仪表盘列表进入。
设备明细页面,提供资源的详细监控数据,用户可以选择其中一个设备来查看其详细的资源使用情况。
左上的结点下拉选择框可以切换设备的明细显示,IP 地址即为该设备的所有网络接口的 IP 地址(仅作信息显示之用):
右边的快速工具条,点击即可打开该设备的 Shell 终端窗口:
利用右边的滚动条往下翻,可见更多的监控项:
CPU 频率与温度监控页面用作开发阶段比对 CPU 频率与 SOC、GPU 温度的关系,看是否会因为风扇散热性能不足导致温度持续上升,进而导致 CPU 强制降频。
RK3399 有 6 个 CPU 核心,分别是小核 0~3, 大核 4~5。一般观测大核即可,因为页面空间原因,同一时间只显示一个核心。通过上部的下拉条可以切换核心显示:
有以下几种方法可以进入设备的 Shell 终端窗口:
点击设备列表页面中点击设备卡上的 按钮;
点击设备明细页面右上角的快速工具条
主板的 Shell 终端窗口是主板 Ubuntu 系统下的 root shell,拥有超级用户的权限,可以执行各种系统维护命令,以及通过 adb 去操作各个子板。
子板的 Shell 终端窗口是 adb shell,可以运行 su 命令切换成 root 用户。
为方便管理,Firefly 集群监控系统引进命令行管理工具 bmc,能快速地进行各种日常子板操作和批量操作,详情请参见《bmc 命令行工具》一章。
准备工作:
重要: 主板和要升级的子板都需要获得有效的 DHCP IP 地址,请务必插好网线。
集群服务器的 OTG USB 口与外部 PC 机的连接必须断开。
固件需要以 “.img” 扩展名结尾,并放到主板的 /home/firefly/Firmware 目录里。
点击左边工具栏上的 图标即可进入子板固件升级页面:
点击右上角的按钮 进入“新增子板固件升级”页面:
选择升级固件,在下拉列表中选择即可。
选择升级设备:左边是可用的设备列表,右边则是待升级的设备列表。
若要升级所有的设备,按“添加全部”按钮,可将所有的可用设备添加到右边的列表中。
若要升级一两个设备,直接鼠标双击对应的设备,可将单个设备添加到右边的列表中。
设备列表上方的编辑框是做筛选之用,可快速筛选出需要的设备。
按“删除全部”按钮,可清空待升级的设备列表。
Ctrl 鼠标点击,可以增加或删除单个设备的选择;Shift 鼠标点击则可以增加或删除连续设备的选择。这跟 Windows 上的列表选择操作是一致的。选择设备后,按相应的“添加”或“删除”按钮即可将设备添加或移除到待升级的设备列表。
按“升级固件”按钮,即可开始固件升级。
刚提交的页面是这样的:
固件的升级时间较长(涉及到后台一系列切换和读写操作),请耐心等待。后台是隔 15 秒刷新一次进度,界面会显示如下的进度页面:
左边是升级设备和进度列表。
右上是升级进度折线图。
右下即是已完成的设备列表(包括成功和出错的)。
鼠标移到左下角用户头像,在弹出菜单中选择“修改密码”:
输入旧密码、新密码和确认新密码,最后按“修改密码”按钮即可。
鼠标移至左下角的帮助图标:
在弹出菜单中选择“检查更新”。如果 BMC 有新版本,将会弹出对话框,并显示更新日志:
点击对话框右上角的“安装”按钮,系统将会自动下载安装包、安装并自动刷新界面。
在终端输入以下命令:
sudo recovery reset
系统进入恢复模式进行恢复出厂设置,大约30s后会自动重启进入系统。
如果Cluster Server R2系统严重损坏无法正常使用,有2种方法:
Cluster Server R2预留的SD卡接口(后视图的7号标签)除了可以用来读写SD卡之外,还可以用来在紧急情况下烧写系统。
插入SD卡到SD卡槽(后视图的7号标签)
重新开机或主机在上电状态下按下复位按键,进入main core启动并进入烧写模式
烧写完成后立即拔出SD卡,系统自动重新启动(升级后的第一次启动略慢,大约比正常启动多30s)。
可以任选一种以下方法来确认是否进入烧写模式:
透过风扇模组(后视图便签2)可以看到,主机内部main core位置会有黄灯闪烁
Console(后视图标签12)接入串口(波特率为115200)会打印烧写信息
接入Mini HDMI,会显示烧写信息
可以任选一种以下方法来确认是否烧写完成:
透过风扇模组(后视图便签2)可以看到,主机内部main core位置会有黄灯停止闪烁,并常亮
Console(后视图标签12)接入串口(波特率为115200)看到Please remove SD CARD!!!, wait for reboot.提示信息后立即拔出SD卡。
接入Mini HDMI,会显示烧写信息,看到Please remove SD CARD!!!, wait for reboot.提示信息后立即拔出SD卡。
拆除main core的核心板,将该核心板当做另外一台Cluster Server R2的子板,通过BMC软件升级相应的主板固件程序
关闭主机电源
按压了蓝色卡扣,拔出主核心板抽屉(后视图标签2风扇模组的正下方底部抽屉),取出main core的核心板
将核心板放人另外一台Cluster Server R2的子板抽屉,进入BMC软件服务进行系统烧写
升级完成后重新安装回主核心板抽屉(后视图标签2风扇模组的正下方底部抽屉)的main core位置,插入抽屉(注意要完全插入否则无法开机)
接上电源,正常启动系统。
子板ADB连接丢失一般有这3种情况:
USB通信链路异常
子板ADB服务异常
子板系统崩溃
常规处理方法:
复位子板所在USB HUB的电源,恢复无效则执行2操作(可能会造成更多子板ADB丢失,建议执行操作2)
使用BMC管理系统来重置子板电源,恢复无效则执行3操作
使用BMC管理系统给该子板重新安装系统
BMC固件已经安装了openstf,但是因为资源占用问题默认关闭openstf,如果想开启服务可以输入以下命令:
sudo systemctl start openstf
注意:安卓10目前不支持openstf
Firefly集群服务器的每一个核心板卡都可以独立运行一个Android系统。用户可以将自己的手机应用部署到每个核心板上。针对云手机应用场景,Firefly集群服务器增加了以下功能。
包括虚拟摄像头、虚拟声卡等。专业技术支持和更详细资料请联系商务。
虚拟摄像头
智能设备在没有安装摄像头或不能安装摄像头的情况下,会导致需要打开摄像头的应用无法使用;而Firefly的虚拟摄像头技术案例可在Firefly集群服务器上虚拟出多个摄像头,通过虚拟摄像头,用户可把准备好的视频文件/图片等加载进去,让这些虚拟摄像头输出这些图像信息。
虚拟声卡
众所周知在没有声卡的设备上播放音频、视频文件,会出现“没有找到音频设备…”“由于声音,设备出现问题…”等等提示而不能播放。而Firefly的虚拟声卡技术案例可在Firefly集群服务器上虚拟出声卡,可以让没有声卡的设备播放音频文件,而不会因为提示没有设备而不能播放。
Firefly 集群服务器上(包括android,linux系统)提供NFS,iSCSI网络存储方案,实现存储资源统一管理。专业技术支持和更详细资料请联系商务。
NFS
NFS( Network File System,网络文件系统),对于在同一个网络上的多个用户间共享目录和文件很有用途。通过使用NFS,用户和程序可以像访问本地文件一样访问远程系统上的文件。
iSCSI
iSCSI( Internet Small Computer System Interface,Internet小型计算机系统接口)。iSCSI使用了TCP/IP协议(一般使用TCP端口860和3260),透过两部计算机之间利用iSCSI的协议来交换SCSI命令,让计算机可以透过高速的局域网集线来把SAN(存储局域网)模拟成为本地的储存装置。可以使用它来连接服务器计算机 (例如,数据库服务器)和磁盘卷上存储阵列。较NFS其读写效率、稳定性更好。
虚拟Android系统是指在一个Soc中,利用容器和虚拟设备技术,虚拟出多个Android系统,每个Android系统之间独立运行。对于用户而言,如果一个子核心板虚拟三个Android设备,那么一个集群服务器最多可以虚拟216个Android设备。虚拟Android系统在应用程序测试、社交媒体运营等邻域有着广泛的应用。
Firefly集群服务器的子核心板有多种配置(参见)。其中RK3399采用双核A72 4核A53架构,集成MaliT860P4 GPU。而RK1126采用RK最新一代NPU架构,AI算力最高可达3T。所以使用Firefly集群服务器作为云计算平台,也是很合适的。针对云计算平台,Firefly集群服务器增强了以下功能支持。
Ubuntu系统在工作环境搭建,部署,更新等环节都非常方便。Firefly集群服务器子核心板搭载的Ubuntu Minimal系统,具有以下优势:
没有桌面环境,占用资源少,在简化网络管理之后,只需40M内存;
针对嵌入式平台,精简系统服务。
提供基于Rockchip VPU Mpp 的视频硬编解码支持。
提供基于Arm Mali GPU的OpenGL、OpenCL支持。
适配QT、Docker、Electron等开发框架。
提供一系列接口,以操作板载资源设备。
系统采用overlayfs文件系统,支持导出rootfs,二次打包,恢复出厂设置等功能
Firefly集群服务器,核心板搭配方案采用RK3399 RK1808 x N,实现了多路网络视频流解码与AI分析。该方案中,集群服务器连接多路网络摄像头进行视频数据采集,利用RK3399强大的视频解码功能对采集到的视频流解码后分发给AI加速芯片RK1808完成AI分析;然后再收集AI分析的结果,实时输出到用户端。
详细介绍参见:多路视频解码与AI分析
所有监控数据都存储到主板的 Prometheus 数据库里,可以使用其命令工具 promtool 去获取监控数据。
监控数据是透过 node_exporter 去获取的。
网页的仪表盘定义 json 文件存放在 /var/lib/grafana/dashboards/ 里。
$ promtool query instant http://127.0.0.1:9090 node_cluster_up
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-01"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-02"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-03"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-04"} => 1 @[1608772515.659]
...
subnode: 子板编号
state:子板状态
android:子板运行的操作系统为 Android。
linux:子板运行操作系统为 Linux。
netrecovery:子板处于辅助升级系统 netrecovery 状态。
offline:子板离线,无法通过 USB 连接检测到。
online:子板能通过 USB 连接检测到,但无法解析进一步的状态。
loader:子板处于 Loader 状态。
fastboot: 子板处于 Fastboot 状态。
adb:子板被识别为 adb 设备,但暂未识别到其操作系统。
adb_offline: 子板被识别为处于 offline 状态的 adb 设备,无法进行正常 adb 操作。
android_recovery: 子板进入了 Android 的 recovery 系统。
metric:
1.0: 子板处于 android 或 linux 状态。
0.0: 子板处于 offline 状态。
0.5: 子板处于上述状态之外。
通过读取底板上的热敏电阻来获取其温度(单位:摄氏度):
$ promtool query instant http://127.0.0.1:9090 'node_hwmon_temp_celsius{chip=~"platform_ntc.*"}'
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60101", job="node", nodename="sub1-01", sensor="temp1"} => 34.779 @[1608773513.849]
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60102", job="node", nodename="sub1-02", sensor="temp1"} => 42.81 @[1608773513.849]
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60103", job="node", nodename="sub1-03", sensor="temp1"} => 43.305 @[1608773513.849]
...
通过读取主机内的 ds18b20 温度传感器的数据来获取主机内的环境温度(单位:摄氏度):
$ promtool query instant http://127.0.0.1:9090 'node_cluster_env_temp_celsius'
单位:RPM (转/分钟)
$ promtool query instant http://127.0.0.1:9090 node_cluster_fan_speed
node_cluster_fan_speed{fan="fan1", instance="127.0.0.1:9100", job="node", nodename="main"} => 7812 @[1607501007.839]
node_cluster_fan_speed{fan="fan2", instance="127.0.0.1:9100", job="node", nodename="main"} => 7936 @[1607501007.839]
...
R2v2 有 10 块能监控转速的风扇。
获取硬盘设备名称和型号:
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_up
node_cluster_disk_up{device="sda", instance="127.0.0.1:9100", job="node", model="ST1000DM010-2EP1", nodename="main"} => 1 @[1609228221.442]
获取硬盘总容量(单位:字节):
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_bytes_total
node_cluster_disk_bytes_total{device="sda", instance="127.0.0.1:9100", job="node", nodename="main"} => 1000204886016 @[1609228289.651]
获取硬盘已使用空间(单位:字节):
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_bytes__used
node_cluster_disk_bytes_used{device="sda", instance="127.0.0.1:9100", job="node", nodename="main"} => 121475072 @[1609228366.843]
$ promtool query instant http://127.0.0.1:9090 node_network_ipaddr
node_network_ipaddr{device="eth0", instance="127.0.0.1:60101", ipaddr="168.168.101.198", job="node", nodename="sub1-01"} => 1 @[1609396443.993]
node_network_ipaddr{device="eth0", instance="127.0.0.1:60102", ipaddr="168.168.100.180", job="node", nodename="sub1-02"} => 1 @[1609396443.993]
node_network_ipaddr{device="eth0", instance="127.0.0.1:60103", ipaddr="168.168.101.145", job="node", nodename="sub1-03"} => 1 @[1609396443.993]
...
device: 网络接口名称,各个子板仅有一个以太网接口 eth0, 主板有多个。每个网络接口对应一个 IP 地址。
ipaddr:IP 地址,如果尚没有取得 IP 地址,则为 “0.0.0.0”。
nodename:子板 sub 编号,或主板 main。
1.2. 硬件控制
功能: 重置子板电源
描述: 通过操控子板的 RESET 脚来重置子板电源,达到强制重启子板的目的。如果子板没有 RESET 脚,则通过关闭、打开电源来实现。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> reset
Web API:GET http://localhost:7070/api/reset/<子板SUB编号>
功能: 重启子板操作系统
描述: 首先通过 adb reboot 命令来重启系统,如果 10 秒内没有反应,则通过复位电源的方式强行重启子板。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> reboot
Web API:GET http://localhost:7070/api/reboot/<子板SUB编号>
功能:打开子板电源
描述:通过操控子板的 POWER 脚来打开子板电源。集群服务器开机默认打开所有子板电源。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> poweron
Web API:GET http://localhost:7070/api/poweron/<子板SUB编号>
功能:关闭子板电源
描述:通过操控子板的 POWER 脚来关闭子板电源。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> poweroff
Web API:GET http://localhost:7070/api/poweroff/<子板SUB编号>
使用脚本添加固件升级任务:
sudo netrecovery-master queue <固件文件绝对路径> <子板SUB编号> [<子板SUB编号> ...]
例如:
sudo netrecovery-master queue /home/firefly/Firmware/xxx.img sub1-01 sub1-02
查看固件升级进度:
$ promtool query instant http://127.0.0.1:9090 node_cluster_firmware_upgrade_stat
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub02", nodename="main", state="done"} => 100 @[1608795873.055]
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub03", nodename="main", state="done"} => 100 @[1608795873.055]
node: 升级固件的子板编号。
state: preparing: 正在准备;flashing: 正在烧写;done: 已完成;error:出错。
metric: 烧写进度百分比,例如 100 表示已全部完成(100%)。
注意:有可能出现同一块子板有两种不同的 state,这时如果存在 state=”flashing” 则表示子板尚在烧写中,因此更稳妥的办法是,先查 flashing 进度,如果有则在升级中,如果没有则再查是完成还是出错:
$ promtool query instant http://127.0.0.1:9090 'node_cluster_firmware_upgrade_stat{node="sub02",state="flashing"}'
$ promtool query instant http://127.0.0.1:9090 'node_cluster_firmware_upgrade_stat{node="sub02",state=~"done|error"}'
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub02", nodename="main", state="done"} => 100 @[1608796078.37]
以下命令使用 bmc_adb,此脚本是对 adb 命令的包装,使用户可以方便地使用子板编号去操作对应子板,而不用理会实际的子板 adb 序列号。当然,adb 命令也可以使用。
在主板上运行:
$ bmc_adb -s sub01 push home.json /data/local/tmp
在主板上运行:
$ bmc_adb -s sub01 pull home.json /data/local/tmp
在主板上运行:
$ bmc_adb -s sub01 shell ifconfig
bmc 命令行工具必须在主板(即结点名称为 main 的设备)的 Shell 终端窗口下运行,当然,远程通过 ssh 连接到主板也可使用。
获取命令帮助:
$ bmc --help
Usage:
bmc list [--offline] []
List all the active nodes usable with adb, optionally matched by pattern
bmc serials
List all the active nodes with coresponding adb serial.
bmc {reset|poweron|poweroff}
Invoke reset, poweron or power off on
bmc state
Show node state
bmc shell [...]
Invoke shell with command.
bmc forall %{node}
列出所有在线(adb 成功连接)设备:
$ bmc list
sub03
sub04
sub05
sub06
sub07
sub08
sub09
sub10
列出所有 adb 状态为 offline 的设备:
$ bmc list --offline
$ bmc serials
sub02 B09CCSUB02 usb:2-1.2.3
sub03 A8232SUB03 usb:2-1.2.4
sub06 4DE1ESUB06 usb:2-1.2.7
sub07 505C3SUB07 usb:2-1.1.2
sub08 FFBCCSUB08 usb:2-1.4
sub09 710AFSUB09 usb:2-1.1.1
$ bmc sub03 reset
okay
关闭子板电源:
$ bmc sub1-01 poweroff
okay
打开子板电源:
$ bmc sub1-01 poweron
okay
查看子板的明细状态:
# 单个子板 $ bmc sub1-01 state android # 所有子板 $ bmc state main: linux sub1-01: android sub1-02: android ... # 所有状态为 offline 的子板 $ bmc state | grep offline sub7-01: offline sub7-02: offline sub7-03: offline ...
列出 sub3-01 的 adb 状态和 ifconfig 结果:
$ bmc sub3-01
node: sub3-01
state: android
adb_state: device
ifconfig:
eth0 Link encap:Ethernet HWaddr ae:bb:8b:e7:b4:38 Driver rk_gmac-dwmac
inet addr:168.168.100.171 Bcast:168.168.255.255 Mask:255.255.0.0
inet6 addr: fe80::7298:5297:6ab9:7fd0/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:66181 errors:0 dropped:0 overruns:0 frame:0
TX packets:190 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4414382 TX bytes:22295
Interrupt:27
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:715 errors:0 dropped:0 overruns:0 frame:0
TX packets:715 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:885911 TX bytes:885911
进入 sub03 的 adb shell:
$ bmc sub03 shell
rk3399_firefly_sr_c11g_jd4:/ $
在 sub03 上运行命令:
$ bmc sub03 shell id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc) context=u:r:shell:s0
bmc 提供了可以批量执行命令的快捷方式 bmc forall,此命令从标准输入读入子板编号,替换命令行上的 %{node} 参数再执行命令。例如:
批量获取子板 adb 状态,%{node} 会被替换为实际的设备结点:
$ echo sub03 sub04 | bmc forall adb -s %{node} get-state
>>> adb -s sub03 get-state
device
>>> adb -s sub04 get-state
device
为了简化操作,bmc forall 对 reset, poweron 和 poweroff 命令提供了快捷支持。
批量重置子板电源:
$ echo sub03 sub04 | bmc forall reset >>> bmc sub03 reset okay >>> bmc sub04 reset okay # 等价于 $ echo sub03 sub04 | bmc forall bmc %{node} reset
另外,bmc forall 也对 shell 命令还提供了简化。
例如,批量获取子板 Android 序列号:
$ echo sub03 sub04 | bmc forall shell getprop ro.serialno
>>> bmc sub03 shell getprop ro.serialno
A82328MDDT
>>> bmc sub04 shell getprop ro.serialno
2E8178MDDT
# 等价于
$ echo sub03 sub04 | bmc forall bmc %{node} shell getprop ro.serialno
promtool 是 Prometheus 提供的命令行工具,可用于查询数据库等功能。
bmc query 是 promtool 的快捷查询方式,不加参数默认返回 node_cluster_up 的值:
$ bmc query
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-01"} => 1 @[1609227870.112]
...
也可以直接指定需要查询的参数,参数请参阅 node_exporter 文档和 BMC 的 API 说明。
以下是插入硬盘后查询其状态:
$ bmc query node_cluster_disk_up
node_cluster_disk_up{device="sda", instance="127.0.0.1:9100", job="node", model="ST1000DM010-2EP1", nodename="main"} => 1 @[1609228042.393]
命令格式:
bmc {main|sub??} vendor []
:
sn: 对应 VENDOR_SN_ID,用来修改 Android 系统的 ro.serialno 属性。
lan: 对应 VENDOR_LAN_MAC_ID, eth0 网卡的 MAC 地址,设置后重启生效。
更多类型请在主控板运行:/usr/share/bmc/vendor_storage_linux -h。
: 该参数可选,若提供则写入,否则是读取。
例如,要对 sub8-09 写入 MAC 地址 ae:0e:fb:84:0f:c2:
# 写入
$ bmc sub8-09 vendor lan ae0efb840fc2
# 读取
$ bmc sub8-09 vendor lan
该命令实际是对 /usr/share/bmc/vendor_storage_linux (Linux 系统) 和 /usr/share/bmc/vendor_storage_android (Android 系统) 的包装,更高级的用法可以直接调用原始命令。
列出主板和所有子板的软硬件版本号:
$ bmc versions
main linux OS:Ubuntu18.04.4 HW:v1.0
sub1-01 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
sub1-02 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
sub1-03 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
...
编译 Android 对机器的配置要求较高:
64 位 CPU
16GB 物理内存 交换内存
250GB 空闲的磁盘空间
建议使用 Ubuntu 18.04 操作系统或更高版本
Ubuntu 16.04 或 18.04 软件包安装参考:
sudo apt-get update
sudo apt-get install git gnupg flex bison gperf libsdl1.2-dev
libesd-java libwxgtk3.0-dev squashfs-tools build-essential zip curl
libncurses5-dev zlib1g-dev pngcrush schedtool libxml2 libxml2-utils
xsltproc lzop libc6-dev schedtool g -multilib lib32z1-dev lib32ncurses5-dev
lib32readline-dev gcc-multilib libswitch-perl libssl-dev unzip zip device-tree-compiler
liblz4-tool python-pyelftools python3-pyelftools -y
由于每个人的PC系统版本和环境配置不一样,安装软件包后编译并不一定都会成功,可能会出现缺少某些软件包而引起的错误,如:
OBJCOPY spl/u-boot-spl-nodtb.bin
CAT spl/u-boot-spl-dtb.bin
COPY spl/u-boot-spl.bin
CFGCHK u-boot.cfg
ERROR: No 'dtc', please: apt-get install device-tree-compiler
此时视报错信息去安装缺少的软件包(dtc)即可
如果Kernel编译报lz4的错误:
LZ4C arch/arm64/boot/Image.lz4
Incorrect parameters
Usage :
lz4 [arg] [input] [output]
input : a filename
with no FILE, or when FILE is - or stdin, read standard input
Arguments :
-1 : Fast compression (default)
-9 : High compression
-d : decompression (default for .lz4 extension)
-z : force compression
-f : overwrite output without prompting
-h/-H : display help/long help and exit
arch/arm64/boot/Makefile:31: recipe for target 'arch/arm64/boot/Image.lz4' failed
可以先编译Android下面的lz4并替换系统的lz4
mmm external/lz4/
sudo cp /usr/bin/lz4 /usr/bin/lz4.org # 备份
sudo cp out/host/linux-x86/bin/lz4 /usr/bin/lz4 # 替换系统原有lz4
如果编译出现这种情况:
error: external/crosvm/rutabaga_gfx/Android.bp:91:1: "rutabaga_gfx_host_test_src_lib" depends on undefined module "libgfxstream_backend"
error: external/crosvm/rutabaga_gfx/Android.bp:13:1: "librutabaga_gfx" depends on undefined module "libgfxstream_backend"
那是因为需要先编译一次 Android 上层才可以,或者也可以直接从以下链接下载 lz4 到系统中,直接进行替换。
sudo cp /usr/bin/lz4 /usr/bin/lz4.org # 备份
sudo cp lz4 /usr/bin/lz4
核心板 Core-3399-JD4 支持 Android10.0
由于 SDK 较大,可以去下载页面选择云盘下载 Firefly-RK3399_Android10.0_git_20210114.7z:
下载完成后,在解压前先校验下 MD5 码:
$ md5sum /path/to/Firefly-RK3399_Android10.0_git_20210114.7z.001
$ md5sum /path/to/Firefly-RK3399_Android10.0_git_20210114.7z.002
10bf3ca46fa629f1965c5c9c8608db7e Firefly-RK3399_Android10.0_git_20210114.7z.001
bd4c36fe268420bf6efe1a2617ab6b8b Firefly-RK3399_Android10.0_git_20210114.7z.002
然后解压:
cd ~/proj/
7z x ./Firefly-RK3399_Android10.0_git_20210114.7z.001 -ork3399_Android10.0cd ./rk3399_Android10.0
git reset --hard
注意:解压后务必要先更新下远程仓库。以下为从 gitlab 处更新的方法:
#1. 进入SDK根目录
cd ~/proj/rk3399_Android10.0
#2. 下载远程bundle仓库
git clone https://gitlab.com/TeeFirefly/rk3399-android10.0-bundle.git .bundle
#3. 若下载仓库失败,目前bundle仓库占用空间较大,所以同步的时候可能会出现卡住或失败的问题,
# 可以从下方百度云链接下载并解压到SDK根目录,解压指令如下:
7z x rk3399-android10.0-bundle.7z -r -o. && mv rk3399-android10.0-bundle/ .bundle/
#4. 更新SDK,并且后续更新不需要再次拉取远程仓库,直接执行以下命令即可
.bundle/update
#5. 按照提示已经更新内容到 FETCH_HEAD,同步FETCH_HEAD到firefly分支
git rebase FETCH_HEAD
./FFTools/make.sh -d rk3399-firefly-cs-r2 -j8 -l rk3399_firefly_cs_r2-userdebug
./FFTools/mkupdate/mkupdate.sh -l rk3399_firefly_cs_r2-userdebug
编译前执行如下命令配置环境变量:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
编译 kernel:
cd ~/proj/rk3399_Android10.0/kernel/
make ARCH=arm64 firefly_defconfig android-10.config rk3399.config
make ARCH=arm64 BOOT_IMG=../rockdev/Image-rk3399_firefly_cs_r2/boot.img rk3399-firefly-cs-r2.img -j8
注意:若进行内核debug,需要将resource.img和kernel.img打包进去boot.img后对boot分区进行烧写才能生效。
编译 uboot:
cd ~/proj/rk3399_Android10.0/u-boot/
./make.sh rk3399
编译 Android:
cd ~/proj/rk3399_Android10.0/
source FFTools/build.sh
lunch rk3399_firefly_cs_r2-userdebug
make -j8
./mkimage.sh
打包成统一固件 update.img
编译完可以用Firefly官方的脚本打包成统一固件,执行如下命令:
cd ~/proj/rk3399_Android10.0/
./FFTools/mkupdate/mkupdate.sh -l rk3399_firefly_cs_r2-userdebug
打包完成后将在rockdev/Image-rk3399_firefly_cs_r2/ 目录下生成统一固件: product名XXX_XXX_日期XXX.img 在 Windows 下打包统一固件 update.img 也很简单,将编译生成的文件拷贝到 AndroidTool 的 rockdevImage 目录中,然后运行 rockdev 目录下的 mkupdate.bat 批处理文件即可创建 update.img 并存放到 rockdevImage 目录里。
boot.img 包含ramdis、kernel、dtb
dtbo.img Device Tree Overlays
kernel.img includekernel,目前无法单独烧写,需要打包到boot.img内烧写
MiniLoaderAll.bin 包含一级loader
misc.img 包含recovery-wipe开机标识信息,烧写后会进行recovery
odm.img 包含android odm,包含在super.img分区内,单独烧写需要用fastboot烧写
parameter.txt 包含分区信息
pcba_small_misc.img 包含pcba开机标识信息,烧写后会进入简易版pcba模式
pcba_whole_misc.img 包含pcba开机标识信息,烧写后会进入完整版pcba模式
recovery.img 包含recovery-ramdis、kernel、dtb
resource.img 包含dtb,kernel和uboot阶段的log及uboot充电logo,目前无法单独烧写,需要打包到boot.img内烧写
super.img 包含odm、vendor、system分区内容
system.img 包含android system,包含在super.img分区内,单独烧写需要同fastboot烧写
trust.img 包含BL31、BL32
uboot.img 包含uboot固件
vbmeta.img 包含avb校验信息,用于AVB校验
vendor.img 包含android vendor,包含在super.img分区内,单独烧写需要同fastboot烧写
update.img 包含以上需要烧写的img文件,可以用于工具直接烧写整个固件包
核心板 Core-3588SJD4 支持 Android12.0
SDK 源码与 bundle 压缩包均存放在云盘中。SDK通过邮件的方式获取,把订单号发送到sales@t-firefly.com邮箱并注明需要的SDK名称firefly_rk3588_android12.0_git_20220311
下载完成后,在解压前先校验下 MD5 码:
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.001
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.002
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.003
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.004
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.005
$ md5sum /path/to/firefly_rk3588_android12.0_git_20220311.7z.006
8f48ca82f247426d0a7111b851d65f0f firefly_rk3588_android12.0_git_20220311.7z.001
e99d68485860b86c2ec5b67aeda7249d firefly_rk3588_android12.0_git_20220311.7z.002
cb45fc9e39848b459398467c08acd6f1 firefly_rk3588_android12.0_git_20220311.7z.003
7774a64cc73dbf4381c100ad1d703fa9 firefly_rk3588_android12.0_git_20220311.7z.004
cd53c8c752a5162a0638da1cf9a0ed8f firefly_rk3588_android12.0_git_20220311.7z.005
fd7744c8098791a8f1dd62527fcac32c firefly_rk3588_android12.0_git_20220311.7z.006
然后解压
cd ~/proj/
7z x ./firefly_rk3588_android12.0_git_20220311.7z.001 -oRK3588_Android12.0
cd ./RK3588_Android12.0
git reset --hard
注意:不要在共享文件夹、挂载文件夹以及非英文目录解压SDK,避免产生不必要的错误
下载 SDK 后,从 gitlab 处更新代码的方法:
#1. 进入 SDK 根目录
cd ~/proj/RK3588_Android12.0
#2. 下载远程 bundle 仓库
git clone https://gitlab.com/T-Firefly/rk3588-android12.0-bundle.git .bundle
#3. bundle仓库会随着更新的资源越多而会越来越大,如果bundle仓库下载速度缓慢或若下载失败,
# 请在资源下载界面选择对应的机器bundle文件进行下载并解压到SDK根目录,解压指令如下:
7z x rk3588-android12.0-bundle.7z -r -o. && mv rk3588-android12.0-bundle .bundle
#4. 更新 SDK,并且后续更新不需要再次拉取远程仓库,直接执行以下命令即可
.bundle/update
#5. 按照提示已经更新内容到 FETCH_HEAD,同步 FETCH_HEAD 到 firefly 分支
git rebase FETCH_HEAD
./FFTools/make.sh -d rk3588s-firefly-cs-r2 -j8 -l rk3588s_firefly_cs_r2-userdebug
./FFTools/mkupdate/mkupdate.sh -l rk3588s_firefly_cs_r2-userdebug
编译 kernel:
cd ~/path/to/sdk/kernel-5.10
export PATH=../prebuilts/clang/host/linux-x86/clang-r416183b/bin:$PATH
alias msk='make CROSS_COMPILE=aarch64-linux-gnu- LLVM=1 LLVM_IAS=1'
msk ARCH=arm64 firefly_defconfig android-11.config pcie_wifi.config
msk ARCH=arm64 BOOT_IMG=../rockdev/Image-rk3588s_firefly_cs_r2/boot.img rk3588s-firefly-cs-r2.img -j8
编译 uboot:
cd ~/path/to/sdk/u-boot/
./make.sh rk3588
编译 Android:
cd ~/path/to/sdk/
source build/envsetup.sh
lunch rk3588s_firefly_cs_r2-userdebug
make installclean
make -j8
./mkimage.sh
打包成统一固件 update.img
编译完可以用Firefly官方的脚本打包成统一固件,执行如下命令:
cd ~/path/to/sdk/
./FFTools/mkupdate/mkupdate.sh -l rk3588s_firefly_cs_r2-userdebug
打包完成后将在rockdev/Image-rk3588s_firefly_cs_r2/ 目录下生成统一固件: product名XXX_XXX_日期XXX.img 在 Windows 下打包统一固件 update.img 也很简单,将编译生成的文件拷贝到 AndroidTool 的 rockdevImage 目录中,然后运行 rockdev 目录下的 mkupdate.bat 批处理文件即可创建 update.img 并存放到 rockdevImage 目录里。
为了方便用户的使用与开发,官方提供了 Linux 开发的整套 SDK,本章详细的说明 SDK 的具体用法。
注意: Linux SDK只适用于集群服务器子板的系统开发。
核心板 Core-3399JD4 支持 Ubuntu 18.04
由于 Firefly_Linux_SDK 源码包比较大,部分用户电脑不支持4G以上文件或单个文件网络传输较慢, 所以我们采用分卷压缩的方法来打包SDK。用户可以通过如下方式获取 Firefly_Linux_SDK源码包:Firefly_Linux_SDK源码包
下载完成后先验证一下 MD5 码:
$ md5sum rk3399_linux_release_v2.5.1_20210301_split_dir/*firefly_split*
2cf71e64d35eb8083a4a0fc30c256484 rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file0
f0e9292b3816a8f1ce0eb1eeb483ad56 rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file1
c6aaa5d761d0e7917bea1cb78a0e7229 rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file2
16022cc729d06a28fec30ac52885d91c rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file3
565426354c01d56c7d48479dd7f3c35b rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file4
313d311f1705fbfb7bfc45b7937ecf24 rk3399_linux_release_v2.5.1_20210301_split_dir/rk3399_linux_release_v2.5.1_20210301_firefly_split.file5
确认无误后,就可以解压:
cat rk3399_linux_release_v2.5.1_20210301_split_dir/*firefly_split* | tar -xzv
#本SDK文件夹内包含一个 .repo 目录,解压之后,在当前目录下执行以下操作
cd rk3399_linux_release_v2.5.1_20210301
ls -al
.repo/repo/repo sync -l
.repo/repo/repo sync -c --no-tags
.repo/repo/repo start firefly --all
后续可以使用以下命令更新 SDK
.repo/repo/repo sync -c --no-tags
目录:
── linux_sdk
├── app
├── buildroot buildroot 根文件系统的编译目录
├── build.sh -> device/rockchip/common/build.sh 全自动编译脚本
├── device 编译相关配置文件
├── distro debian 根文件系统生成目录
├── docs 文档
├── envsetup.sh -> buildroot/build/envsetup.sh
├── external
├── kernel 内核
├── Makefile -> buildroot/build/Makefile
├── mkfirmware.sh -> device/rockchip/common/mkfirmware.sh rockdev链接更新脚本
├── prebuilts
├── rkbin
├── rkflash.sh -> device/rockchip/common/rkflash.sh 烧写脚本
├── rootfs debian根文件系统编译目录
├── tools 烧写、打包工具
└── u-boot
Ubuntu 固件:(根文件系统请使用官方提供的根文件系统镜像)
sudo apt-get update
sudo apt-get install repo git-core gitk git-gui gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler
gcc-aarch64-linux-gnu mtools parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools
linaro-image-tools gcc-arm-linux-gnueabihf libssl-dev liblz4-tool genext2fs lib32stdc 6
gcc-aarch64-linux-gnu g conf autotools-dev libsigsegv2 m4 intltool libdrm-dev curl sed make
binutils build-essential gcc g bash patch gzip bzip2 perl tar cpio python unzip rsync file bc wget
libncurses5 libqt4-dev libglib2.0-dev libgtk2.0-dev libglade2-dev cvs git mercurial rsync openssh-client
subversion asciidoc w3m dblatex graphviz python-matplotlib libc6:i386 libssl-dev texinfo fakeroot
libparse-yapp-perl default-jre patchutils
注意: Ubuntu17.04 或者更高的系统还需要如下依赖包:
sudo apt-get install lib32gcc-7-dev g -7 libstdc -7-dev
编译前配置
配置文件 CS-R2-3399-jd4-sub-ubuntu.mk:
./build.sh CS-R2-3399-jd4-sub-ubuntu.mk
文件路径在 device/rockchip/rk3399/
如果配置文件生效会连接到 device/rockchip/.BoardConfig.mk ,检查该文件可以验证是否配置成功
#!/bin/bash
CMD=`realpath $BASH_SOURCE`
CUR_DIR=`dirname $CMD`
source $CUR_DIR/BoardConfig.mk
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=firefly-rk3399
# Kernel defconfig
export RK_KERNEL_DEFCONFIG=firefly_linux_defconfig
# Kernel dts
export RK_KERNEL_DTS=rk3399-firefly
# parameter for GPT table
export RK_PARAMETER=parameter-ubuntu.txt
# packagefile for make update image
export RK_PACKAGE_FILE=rk3399-ubuntu-package-file
# Set rootfs type, including ext2 ext4 squashfs
export RK_ROOTFS_TYPE=ext4
# rootfs image path
export RK_ROOTFS_IMG=ubuntu_rootfs/rk3399_ubuntu_rootfs.img
# recovery ramdisk
export RK_RECOVERY_RAMDISK=recovery-arm64.cpio.gz
# Set userdata partition type
export RK_USERDATA_FS_TYPE=ext4
# Buildroot config
export RK_CFG_BUILDROOT=
# Recovery config
export RK_CFG_RECOVERY=
#OEM config
export RK_OEM_DIR=
#userdata config
export RK_USERDATA_DIR=
注意,十分重要!!
把得到的镜像放到 SDK 的指定目录:
#解压
tar -xvf rk3399_ubuntu18.04_LXDE.img.tgz
#sdk根目录下
mkdir ubunturootfs
mv rk3399_ubuntu18.04_LXDE.img ubunturootfs/
#修改firefly-rk3399-ubuntu.mk文件
vim device/rockchip/RK3399/firefly-rk3399-ubuntu.mk
#把RK_ROOTFS_IMG属性改成ubuntu文件系统镜像得路径(也就是rk3399_ubuntu18.04_LXDE.img)
RK_ROOTFS_IMG=ubunturootfs/rk3399_ubuntu18.04_LXDE.img
注意: Ubuntu 根文件系统镜像存放路径不能错。
#全自动编译的固件
$ ./build.sh
#部分编译
$ ./build.sh kernel
$ ./build.sh uboot
$ ./build.sh recovery
#运行 ./mkfirmware.sh 会自动更新 rockdev/rootfs.img 的链接。
$ ./build.sh firmware
#固件打包
#每次打包固件前先确保 rockdev/ 目录下文件链接是否正确:
$ ls -l
├── boot.img -> ~/project/linux_sdk/kernel/boot.img
├── idbloader.img -> ~/project/linux_sdk/u-boot/idbloader.img
├── MiniLoaderAll.bin -> ~/project/linux_sdk/u-boot/rk3399_loader_v1.14.115.bin
├── misc.img -> ~/project/linux_sdk/device/rockchip/rockimg/wipe_all-misc.img
├── parameter.txt -> ~/project/linux_sdk/device/rockchip/RK3399/parameter-ubuntu.txt
├── recovery.img -> ~/project/linux_sdk/buildroot/output/rockchip_rk3399_recovery/images/recovery.img
├── rootfs.img -> ~/project/linux_sdk/ubunturootfs/rk3399_ubuntu18.04_LXDE.img
├── trust.img -> ~/project/linux_sdk/u-boot/trust.img
├── uboot.img -> ~/project/linux_sdk/u-boot/uboot.img
└── userdata.img
#打包统一固件
# 注意:打包前请确认 tools/linux/Linux_Pack_Firmware/rockdev/package-file 是否正确。打包会根据此文件进行分区打包。此文件链接会在 ./build.sh firefly-rk3399-ubuntu.mk 命令时更新,如果配置不对请返回编译前配置一节重新配置一次。
整合统一固件:
$ ./build.sh updateimg
parameter.txt 包含了固件的分区信息十分重要,你可以在 device/rockchip/rk3399 目录下找到一些 parameter.txt 文件,下面以 parameter-debian.txt 为例子做介绍:
FIRMWARE_VER: 8.1
MACHINE_MODEL: RK3399
MACHINE_ID: 007
MANUFACTURER: RK3399
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3399
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00010000@0x0000a000(boot),0x00010000@0x0001a000(recovery),0x00010000@0x0002a000(backup),0x00020000@0x0003a000(oem),0x00700000@0x0005a000(rootfs),-@0x0075a000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9
CMDLINE 属性是我们关注的地方。以 Uboot 为例 0x00002000@0x00004000(uboot) 中 0x00004000 为 Uboot 分区的起始位置 0x00002000 为分区的大小。后面的分区规则相同。用户可以根据自己需要增减或者修改分区信息,但是请最少保留 uboot, trust, boot, rootfs 分区,这是机器能正常启动的前提条件。parameter-ubuntu.txt 中使用的就是这样的最简分区方案。
分区介绍:
uboot 分区: 烧写 uboot 编译出来的 uboot.img。
trust 分区: 烧写 uboot 编译出来的 trust.img。
misc 分区: 烧写 misc.img。开机检测进入 recovery 模式。(可省略)
boot 分区: 烧写 kernel 编译出来的 boot.img 包含 kernel 和设备树信息。
recovery 分区: 烧写 recovery.img。(可省略)
backup 分区: 预留,暂时没有用。后续跟 android 一样作为 recovery 的 backup 使用。(可省略)
oem 分区: 给厂家使用,存放厂家的 app 或数据。只读。代替原来音箱的 data 分区。挂载在/oem 目录。(可省略)
rootfs 分区: 存放 buildroot 或者 debian 编出来的 rootfs.img,只读.
userdata 分 区 : 存放 app 临时生成的文件或者是给最终用户使用。可读写,挂载在 /userdata 目录下。(可省略)
package-file文件应当与 parameter 保持一致,用于固件打包。可以在 tools/linux/Linux_Pack_Firmware/rockdev 下找到相关文件。以 rk3399-ubuntu-package-file 为例介绍:
# NAME Relative path
#
#HWDEF HWDEF
package-file package-file
bootloader Image/MiniLoaderAll.bin
parameter Image/parameter.txt
trust Image/trust.img
uboot Image/uboot.img
boot Image/boot.img
rootfs:grow Image/rootfs.img
backup RESERVED
以上是 SDK 编译后生成的镜像文件。根据 parameter.txt 只打包自己用到的 img 文件。
核心板 Core-3588SJD4 支持 Ubuntu 20.04
首先准备一个空文件夹用于存放 SDK,建议在 home 目录下,本文以 ~/proj 为例
不要在虚拟机共享文件夹以及非英文目录存放、解压SDK,且不要使用 sudo root 权限操作, 避免产生不必要的错误
获取 SDK 需要先安装:
sudo apt update
sudo apt install -y repo git python
方法一(推荐国内用户使用)
SDK 源码存放于 gitlab,国内用户可能下载完整的 SDK 仓库速度比较慢,所以我们提供了一个 SDK 基础包(Linux SDK),国内用户只需要在此基础包上同步 gitlab 上的代码就可以了
下载完成后先验证一下 MD5 码:
$ md5sum rk3588_linux_release_20230114_v1.0.6c_0*
c3bcb3f92bd139f72551c89f75d39bfa rk3588_linux_release_20230114_v1.0.6c_00
ebb658571a645d4af1e2b569709480b7 rk3588_linux_release_20230114_v1.0.6c_01
9761cc324e9f7133500b590c441b0307 rk3588_linux_release_20230114_v1.0.6c_02
7adc9fe2158d7681554dce1def238f49 rk3588_linux_release_20230114_v1.0.6c_03
3d9201e3849b8a523c05920bebe28b39 rk3588_linux_release_20230114_v1.0.6c_04
6faaee006fe60fc9be60a64a01506cb6 rk3588_linux_release_20230114_v1.0.6c_05
确认无误后,就可以解压:
# 解压
mkdir -p ~/proj/rk3588_sdk
cd ~/proj/rk3588_sdk
cat path/to/rk3588_linux_release_20230114_v1.0.6c_0* | tar -xv
# 导出数据
.repo/repo/repo sync -l
方法二
通过 repo 拉取代码,此方法对网络要求较高,有条件可以使用
可选择获取完整 SDK 或者 BSP:
mkdir ~/proj/rk3588_sdk/
cd ~/proj/rk3588_sdk/
## 完整 SDK
repo init --no-clone-bundle --repo-url https://gitlab.com/firefly-linux/git-repo.git -u https://gitlab.com/firefly-linux/manifests.git -b master -m rk3588_linux_release.xml
## BSP ( 只包含基础仓库和编译工具 )
## BSP 包括 device/rockchip 、docs 、 kernel 、 u-boot 、 rkbin 、 tools 和交叉编译链
repo init --no-clone-bundle --repo-url https://gitlab.com/firefly-linux/git-repo.git -u https://gitlab.com/firefly-linux/manifests.git -b master -m rk3588_linux_bsp_release.xml
执行如下命令同步代码:
# 进入 SDK 根目录
cd ~/proj/rk3588_sdk
# 同步
.repo/repo/repo sync -c --no-tags
.repo/repo/repo start firefly --all
后续可以使用以下命令更新 SDK:
.repo/repo/repo sync -c --no-tags
因为网络环境等原因,.repo/repo/repo sync -c --no-tags 命令更新代码可能会失败,可多次反复执行。
$ tree -L 1
.
├── app
├── buildroot # Buildroot 根文件系统编译目录
├── build.sh -> device/rockchip/common/build.sh # 编译脚本
├── device # 编译相关配置文件
├── docs # 文档
├── envsetup.sh -> buildroot/build/envsetup.sh
├── external
├── kernel
├── Makefile -> buildroot/build/Makefile
├── mkfirmware.sh -> device/rockchip/common/mkfirmware.sh # 链接脚本
├── prebuilts # 交叉编译工具链
├── rkbin
├── rkflash.sh -> device/rockchip/common/rkflash.sh # 烧写脚本
├── tools # 工具目录
├── u-boot
在 device/rockchip/rk3588/ 目录下,有不同板型的配置文件(xxxx.mk),用于管理 SDK 每个环节的编译配置,相关配置介绍:
# Target arch
export RK_ARCH=arm64 # 64位 ARM 架构
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=xxxx_defconfig # u-boot 配置文件
# Kernel defconfig
export RK_KERNEL_DEFCONFIG=xxxx_defconfig # kernel 配置文件
# Kernel defconfig fragment
export RK_KERNEL_DEFCONFIG_FRAGMENT=xxxx.config # kernel 配置文件(fragment)
# Kernel dts
export RK_KERNEL_DTS=xxxx.dts # dts 文件
# parameter for GPT table
export RK_PARAMETER=parameter-xxxx.txt # 分区表
# rootfs image path
export RK_ROOTFS_IMG=ubuntu_rootfs/rootfs.img # 根文件系统路径
路径:device/rockchip/rk3588/parameter-xxxxxx-fit.txt
FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3588
MACHINE_ID: 007
MANUFACTURER: RK3588
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00020000@0x00008000(boot:bootable),0x00040000@0x00028000(recovery),0x00010000@0x00068000(backup),0x00c00000@0x00078000(rootfs),0x00040000@0x00c78000(oem),-@0x00cb8000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9
CMDLINE 属性是我们关注的地方,以 uboot 为例, 0x00002000@0x00004000(uboot) 中 0x00004000 为uboot 分区的起始位置,0x00002000 为分区的大小,以此类推。
package-file 文件用于打包固件时确定需要的分区镜像和镜像路径,同时它需要与 parameter.txt 文件保持一致。
路径:tools/linux/Linux_Pack_Firmware/rockdev/rk3588-package-file
# NAME Relative path
#
#HWDEF HWDEF
package-file package-file
bootloader Image/MiniLoaderAll.bin
parameter Image/parameter.txt
uboot Image/uboot.img
misc Image/misc.img
boot Image/boot.img
recovery Image/recovery.img
rootfs Image/rootfs.img
userdata RESERVED
backup RESERVED
本章介绍 Ubuntu 固件的编译流程,推荐在 Ubuntu 18.04 系统环境下进行开发,若使用其它系统版本,可能需要对编译环境做相应调整。
本教程的编译部分适用于 v1.0.6e 以上 SDK 版本
$ readlink -f .repo/manifest.xml
/home/daijh/p/rk3588/.repo/manifests/rk3588/rk3588_linux_release_20230301_v1.0.6e.xml
搭建编译环境:
sudo apt-get install repo git ssh make gcc libssl-dev liblz4-tool
expect g patchelf chrpath gawk texinfo chrpath diffstat binfmt-support
qemu-user-static live-build bison flex fakeroot cmake gcc-multilib g -multilib
unzip
device-tree-compiler ncurses-dev
在 device/rockchip/rk3588/ 目录下,有不同板型的配置文件,选择配置文件:
./build.sh CS-R2-3588s-jd4-sub-minimal-ubuntu.mk
下载根文件系统:Ubuntu 根文件系统(64位),放到 SDK 路径下
7z x ubuntu-aarch64-rootfs.7z
mkdir ubuntu_rootfs
mv ubuntu-aarch64-rootfs.img ubuntu_rootfs/rootfs.img
开始编译
./build.sh
生成的完整固件会保存到 rockdev/pack/ 目录。
编译 u-boot
./build.sh uboot
编译 kernel
./build.sh extboot
编译 recovery
./build.sh recovery
下载根文件系统:Ubuntu 根文件系统(64位),放到 SDK 路径下
7z x ubuntu-aarch64-rootfs.7z
mkdir ubuntu_rootfs
mv ubuntu-aarch64-rootfs.img ubuntu_rootfs/rootfs.img
更新各部分镜像链接到 rockdev/ 目录
./mkfirmware.sh
打包固件,生成的完整固件会保存到 rockdev/pack/ 目录
./build.sh updateimg
硬件看门狗的主体是一个定时电路,其主要作用是监控、管理CPU的运行状态,并对处于异常状态中的CPU进行复位操作,使其能重新工作。
Android10.0 出厂固件没有打开硬件看门狗,如果客户需要可自行实现软件程序去使用硬件看门狗,下面提供硬件看门狗的操作方法:
使能看门狗
echo e > "/dev/wdt_crl"
设置超时时间(喂狗)
支持设置4种超时时间:0.64s、2.56s、10.24s、40.96s,对应往设备节点里写0、1、2、3。客户可根据自己的需要设置不同的超时时间,例如客户需要设置超时时间为2.56s,则为:
echo 1 > "/dev/wdt_crl"
软件程序需要定时设置超时时间对看门狗内的定时器清零(俗称“喂狗”)。
当CPU出现故障,则不能继续提供“喂狗”信号,就使得看门狗内的定时器不断累加而溢出,从而产生复位信号对CPU进行复位重启系统,使CPU重新工作。
关闭看门狗
echo d > "/dev/wdt_crl"
原因有多样,请按照以下顺序逐一排查:
将显示时间范围调整到最近半小时,看有没有输出。
运行 adb devices 看有没有设备列出。
如果没有,确保 USB OTG 口没有连接到电脑上,如果 USB OTG 口也没有连接,请检查核心板连接和电源,排除硬件问题。
运行 bmc query ,正常情况下有如下返回:
root@firefly:~# bmc query
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", subnode="main"} => 1 @[1603356844.328]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", subnode="sub01"} => 1 @[1603356844.328]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", subnode="sub02"} => 1 @[1603356844.328]
...
如果没有,检查主板上的 node_exporter 有没有运行:
root@firefly:~# bmc main metrics | grep node_cluster_up
# HELP node_cluster_up Value is 1 if the cluster subnode is 'up', 0 otherwise.
# TYPE node_cluster_up gauge
node_cluster_up{state="android",subnode="sub02"} 1
node_cluster_up{state="android",subnode="sub03"} 1
...
如果没有输出,则主板上的 node_exporter 运行出错。
如果有输出, Prometheus 服务并没有去收集主板的 node_exporter 数据,运行出错。
运行 sudo systemctl status prometheus 查看该服务的状态。
运行 sudo journalctl -u prometheus 查看该服务的运行日志,定位错误的原因。
如果日志含有出错信息:”Handle Corrupt Prometheus Write-Ahead Log (WAL)”
请尝试删除该坏文件并重启服务:
sudo systemctl restart prometheus
如果日志含有出错信息:”Error on ingesting out-of-order samples”
当服务器时间和浏览器时间不一致, 例如服务器时间是 7-01, 浏览器是 7-21, 这 会导致浏览器发送的查询命令要求返回对于服务器来讲是未来的数据,得到的响应结果为空, 进而导致显示界面为空。
系统默认是使用 NTP 自动更新时间的,如果由于网络原因无法使用 NTP,就要手工同步时间:
sudo timedatectl set-ntp false # 关闭 NTP
sudo timedatectl set-timezone Asia/Shanghai # 设置本地时区
sudo timedatectl set-time "2021-10-14 15:48:29" # 设置本地时间
timedatectl status # 检查结果,注意时区和时间
然后重置 Prometheus:
sudo systemctl stop prometheus
sudo rm -rf /var/lib/prometheus/metrics2/*
sudo systemctl start prometheus
子板固件升级系统分为两部分:
Web 前端负责添加固件升级申请和升级进度的显示。
后端netrecovery-master 负责实际的子板固件升级和进度更新。
子板固件升级流程为:
切换子板到 Loader 模式。
对处于 Loader 模式的子板设备写入辅助升级固件并重启进入升级系统(下称 netrecovery 模式)。
对子板设置 DHCP IP 地址。
子板运行固件升级程序,通过网络下载主板上的固件,同时烧写到 eMMC 存储。
子板烧写成功,重启。
子板固件升级成功的必要条件:
确保子板能够获取 DHCP IP 地址,而且主板与子板的网络要能相通。
集群服务器的 OTG USB 口与外部 PC 机的连接必须断开。
固件文件放在 /home/firefly/Firmware 目录里,后缀名为 “.img”。
这个需要检查一下 netrecovery-master 的日志:
sudo journalctl -f -u netrecovery-master
查看是否有什么出错信息导致程序异常退出。
要重启该服务,可以运行:
sudo systemctl restart netrecovery-master
设备无法切换到 Loader 模式,或者 Loader 模式下无法刷入 netrecovery 均会出现这种错误。
可以尝试过段时间后重试。如果都不行,只能使用 USB 线刷方式重新烧录固件。
下面以子板 sub1-01 为例子,请换成实际的设备号。
# 看子板端日志
$ bmc sub1-01 shell
$ cd /tmp/log
$ cat history # 查看命令列表,第一个数字是进程号
$ cat *.err # 查看错误输出
# 如果子板端看不了,可以看一下主板端的运行结果:
$ cd /var/netrecovery/sub1-01/state
$ cat master-*.out
$ cat history # 主板会将子板的日志文件下载到本地供查看
$ cat *.err # 查看错误输出
运行服务状态:
sudo systemctl status prometheus
运行服务日志:
sudo journalctl -u prometheus
sudo du -hs /var/lib/prometheus/metrics2
请修改 /etc/default/prometheus 配置文件,当前默认的设定是:
ARGS="--storage.tsdb.retention.time=7d --storage.tsdb.retention.size=4GB"
即仅保留 7 天以内、最大 4GB 的数据。
以下操作会删除 Prometheus 所有数据并重启服务:
```shell
sudo systemctl stop prometheus
sudo rm -rf /var/lib/prometheus/metrics2/*
sudo systemctl start prometheus
```
node_filefd_allocated 表示已经分配的文件描述符的数量。这个数字越高表明打开的文件数越多。
参考:
node_context_switches_total 表示进程上下文切换的速率。这个数越高,表明进程数比较多而且切换频繁。
参考:
以sub01为例,静态IP:192.168.1.240,子网掩码:255.255.0.0,网关:192.168.1.1,主DNS:202.96.128.86,副DNS:202.96.128.166:
```shell
bmc_adb -s sub01 root
bmc_adb -s sub01 remount
bmc_adb -s sub01 shell "fireflyapi ethernet setIpAddress 1 192.168.1.240 255.255.0.0 192.168.1.1 202.96.128.86 202.96.128.166"
```
以sub01为例:
```shell
bmc_adb -s sub01 root
bmc_adb -s sub01 remount
bmc_adb -s sub01 shell "fireflyapi ethernet setIpAddress 0"
```