1. 项目概述:从单核到异构,解锁开发板的并行处理潜能
最近在折腾一块瑞芯微RK3568的开发板,具体型号是迅为的iTOP-3568。这块板子性能不错,四核A55的架构,在嵌入式领域算是中坚力量了。但玩着玩着,我发现了一个更有意思的玩法——AMP(Asymmetric Multiprocessing,非对称多处理)。简单来说,就是让这块板子同时运行两个独立的操作系统,比如一个实时系统(RTOS)负责高精度的电机控制,另一个功能丰富的Linux系统负责图形界面和网络通信。这就像在一台电脑上开了两个完全独立的“虚拟机”,但性能损耗更低,实时性更有保障。要实现这个“魔法”,第一步也是最关键的一步,就是烧写一个特殊的“AMP镜像”。这个镜像文件里,已经打包好了两个系统的所有代码和数据,并且规划好了各自运行在哪几个CPU核心上、内存怎么分、外设谁管。今天,我就把自己从零开始,给iTOP-3568烧写AMP镜像的完整过程、踩过的坑以及核心原理,详细地梳理一遍。无论你是做工业控制、机器人还是需要复杂人机交互的设备开发者,这套流程都能帮你快速上手,释放RK3568硬件的全部潜力。
2. 核心概念解析:AMP系统与标准系统的本质区别
在动手烧写之前,我们必须先搞清楚,我们要烧的到底是个什么东西。这决定了我们后续所有工具的选择和操作逻辑。
2.1 什么是真正的AMP系统?
很多人容易把AMP和简单的多任务混淆。在一个标准的Linux系统中,虽然也是多核,但所有核心都由同一个Linux内核调度和管理,共享同一套内存空间、设备树和设备驱动。这叫做SMP(对称多处理)。而AMP是另一回事。以我们手头的iTOP-3568为例,它搭载的RK3568芯片有四个ARM Cortex-A55核心。在AMP模式下,我们可以进行这样的划分:
- 核心0 & 核心1:分配给一个实时操作系统,例如FreeRTOS或RT-Thread。这个系统拥有对这两个核心的绝对控制权,以及一块独立且连续的内存区域(比如从物理地址0x08000000开始的128MB)。它直接管理一些对实时性要求极高的外设,比如特定的PWM、GPIO或CAN控制器。
- 核心2 & 核心3:分配给一个功能完整的Linux系统。它管理剩下的内存和大部分外设,如GPU、VPU、USB、以太网等,提供丰富的应用生态。
这两个系统在硬件层面是“老死不相往来”的。它们有各自独立的内核、内存池、中断控制器视图(通过GIC配置)和外设访问权限。它们之间的通信,不能像Linux进程间用共享内存那么简单,必须通过芯片提供的硬件机制,比如基于共享内存的邮箱(Mailbox)或消息传递单元(MPU),进行非常谨慎的、异步的数据交换。我们最终要烧写的“AMP镜像”,就是一个包含了这两个系统所有二进制代码、且明确指定了上述资源划分规则的单一文件包。
2.2 iTOP-3568 AMP镜像的组成剖析
迅为官方提供的AMP镜像,通常是一个以.img为后缀的复合镜像文件。我们可以把它想象成一个精心编排的“集装箱”,里面整齐地摆放着以下几个关键“货柜”:
- 引导加载程序(Bootloader):通常是U-Boot,但它是被特殊修改过的。它的首要任务不再是简单地启动一个内核,而是要根据预定义的配置表,进行硬件资源的初始化与分区。例如,它会初始化GIC,将CPU0和1的中断路由屏蔽,留给RTOS;为RTOS预留出约定的内存区域并标记为“不可侵犯”;最后,分别加载RTOS和Linux内核到指定的内存地址。
- 实时系统(RTOS)镜像:这部分是RTOS内核及其初始化任务的二进制代码,已经被编译成能在指定内存地址直接运行的格式(如bin或elf)。它被放置在镜像中一个固定的偏移位置。
- Linux系统镜像:这部分就是我们更熟悉的组合了:Linux内核(Image)、设备树二进制文件(dtb)、以及根文件系统(rootfs)。在AMP配置中,Linux的设备树(dtb)是至关重要的,它必须“知道”系统中有两个核心已经被占用,有一块内存区域是保留的,有一些外设是不归自己管的。这个dtb文件也是被特殊修改过的。
- 资源划分表(或配置头):这是一个包含元数据的小块区域,可能位于镜像开头或一个独立分区。它明确记录了RTOS镜像的加载地址、入口地址、占用核心ID、预留内存范围等信息。Bootloader就是靠这张“地图”来正确部署两个系统的。
理解了这个结构,你就会明白,烧写AMP镜像不是简单地把一个系统文件拖进去,而是一次性部署一个完整的、预配置好的异构计算环境。
3. 烧写前的关键准备工作:环境与工具链搭建
工欲善其事,必先利其器。给嵌入式板子烧写系统,稳定的环境和正确的工具能避免一大半的玄学问题。
3.1 硬件连接清单与要点
首先,请确保你手头有以下硬件,并正确连接:
- iTOP-3568开发板:本体一块。
- 电源适配器:必须使用官方推荐的12V/2A电源。供电不足会导致烧写过程中板子意外重启,极有可能造成eMMC芯片损坏,板子变砖。
- Type-C数据线:用于连接开发板的Type-C OTG口和电脑的USB口。这条线至关重要!强烈建议使用品牌好、质量优的数据线,劣质线缆可能导致连接不稳定,烧写失败。我吃过亏,用了一根不知名的线,十次有八次在传输大文件时断开。
- MicroSD卡(可选):如果你计划从SD卡启动或烧写,需要准备一张。但本文主要介绍更常用、更稳定的USB烧写方式。
- 串口调试线(USB转TTL):这是你的“眼睛”和“耳朵”。连接开发板的调试串口(通常是UART2,RX/TX/GND三根线)到电脑,通过串口终端软件(如MobaXterm、SecureCRT、PuTTY)查看板子的启动日志和U-Boot命令行。波特率一般设置为1500000。
注意:连接Type-C线时,开发板必须先断电。严禁在板子通电状态下热插拔Type-C线到OTG口,这有很高概率损坏RK3568芯片内部的USB PHY电路。
3.2 软件开发环境配置
烧写工具我们使用瑞芯微官方提供的RKDevTool(或它的图形化版本RKDevTool_Release)。你可以在迅为官方论坛或瑞芯微开发者网站找到它。
- 安装驱动:将开发板断电,按住板子上的恢复键(Recovery)或烧写键(LOAD)不放,然后连接Type-C线到电脑,最后给开发板上电。此时,Windows设备管理器里应该会出现一个“未知设备”或“Rockusb Device”。为其安装
DriverAssitant_v5.1.1驱动包内的驱动程序。安装成功后,设备管理器会显示“Rockchip USB Device”。 - 准备AMP镜像文件:从迅为官方获取
amp_linux_rtos_xxx.img文件。确认其完整性,可以通过校验MD5或SHA256值与官方提供的是否一致。 - 配置RKDevTool:
- 打开RKDevTool,界面通常分为两部分:左侧是存储布局(Storage),右侧是操作按钮和日志。
- 首先,点击“升级固件”选项卡。
- 点击“固件”路径后的按钮,选择你下载的AMP镜像文件(.img)。
- 关键步骤:加载镜像后,工具会解析出镜像内的分区表。你需要仔细核对这个分区表。一个典型的AMP镜像分区可能包括:
loader(引导)、uboot、trust、boot、rootfs,以及一个特殊的rtos分区。确认rtos分区存在且大小合理,这证明了它确实是AMP镜像。
4. 烧写流程全解析:从Loader模式到系统启动
一切就绪,我们开始最核心的烧写操作。整个过程可以分为让板子进入烧写模式、执行烧写、验证结果三个大阶段。
4.1 进入Loader烧写模式
这是让芯片的ROM代码接管,等待通过USB接收新镜像的状态。有两种常用方法:
方法一:按键法(最可靠)
- 开发板完全断电(拔掉电源适配器)。
- 按住板载的恢复键(Recovery)不放。这个键可能被标为“LOAD”或有一个恢复图标。
- 在按住按键的同时,将Type-C数据线连接到电脑USB口。
- 保持按住按键,给开发板接通电源。
- 大约2-3秒后,可以松开按键。此时,RKDevTool的日志窗口通常会显示“发现一个LOADER设备”,并且下方的进度条区域会从灰色变为可操作状态。
方法二:命令法(需进入U-Boot)如果板子里已有系统并能进入U-Boot命令行,则更简单:
- 通过串口连接板子,上电后在U-Boot启动倒计时时按任意键中断启动。
- 在U-Boot命令行中输入:
rockusb 0 mmc 0。这个命令的意思是:从eMMC(mmc 0)启动RockUSB模式。 - 执行后,U-Boot会提示“Entering rockusb mode...”,此时板子重启并自动进入Loader模式。再通过Type-C连接电脑即可。
实操心得:我强烈推荐并始终使用方法一。因为它不依赖板内已有的任何软件状态,是纯粹的硬件行为,成功率几乎是100%。方法二虽然优雅,但如果现有的U-Boot或系统已经有问题,命令可能无法执行。
4.2 执行镜像烧写与关键参数确认
设备进入Loader模式后,RKDevTool界面会刷新。
- 擦除与升级:通常,为了确保干净,建议先点击“擦除Flash”按钮。这会清空eMMC上的所有数据。这是一个危险操作,请再次确认你选对了设备且已备份重要数据!
- 执行烧写:擦除完成后,直接点击“升级”按钮。RKDevTool会开始将AMP镜像文件通过USB传输到开发板的eMMC中。
- 监控过程:此时,你需要密切关注日志窗口和进度条。一个正常的烧写过程会依次显示:
Download Boot Start->Download Boot Success:下载并运行最小引导程序成功。Test Device Start->Test Device Success:测试存储设备(eMMC)成功。Check Chip Start->Check Chip Success:校验芯片信息成功。- 然后开始按分区逐个烧写:
Write,Write... 直到Write。 - 每个分区写入时都会有进度百分比。重点观察
rtos分区的写入,这是AMP镜像区别于普通镜像的标志。 - 全部完成后,显示“
升级完成”或“Download Image Success”。
烧写过程中的一个关键细节:在RKDevTool的“高级功能”或分区表界面,你可以看到每个分区的起始地址和大小。对于AMP镜像,请特别留意rtos分区的起始地址(例如0x08400000)。这个地址必须与RTOS系统在编译时指定的链接地址(Link Address)完全一致!如果不一致,RTOS在启动时从错误的内存地址取指令,会立即崩溃。这个信息通常由镜像提供方(迅为)保证一致性,但作为开发者,了解这个对应关系对后续调试至关重要。
4.3 烧写后启动验证与双系统状态检查
烧写完成,RKDevTool提示成功后,先不要急于关闭工具。
- 断开USB,重新上电:给开发板重新上电(或按复位键)。此时,系统应该从eMMC首次启动。
- 观察串口日志:将串口终端打开,你会看到如瀑布般的启动信息。这是最激动人心的时刻,你需要从中捕捉关键信息来验证AMP是否成功:
- U-Boot日志:最初的几行会显示U-Boot版本。接着,寻找关于CPU和内存初始化的信息。关键行:你会看到类似
CPU0: ARM Cortex-A55 r1p0和CPU1: ARM Cortex-A55 r1p0被标记为Reserved或for RTOS的字样。而CPU2和CPU3被标记为Linux。同时,U-Boot会打印内存映射,其中有一段内存(如0x08000000-0x0fffffff)会被标记为reserved。 - RTOS启动日志:紧接着,U-Boot会跳转到RTOS的入口地址。如果RTOS配置了串口输出,你会看到RTOS的启动信息,例如
[RTOS] Starting scheduler on Core 0...或FreeRTOS Kernel Version...。这表明RTOS已经在核心0和1上成功运行起来了。 - Linux启动日志:RTOS初始化完成后(或并行地),U-Boot会继续启动Linux。你会看到熟悉的Linux内核解压信息:
[ 0.000000] Booting Linux on physical CPU 0x2(注意这里的CPU ID是2或3,对应物理核心2和3)。然后内核初始化,加载设备树,最后挂载根文件系统,出现Linux登录提示符(如iTOP-3568 login:)。
- U-Boot日志:最初的几行会显示U-Boot版本。接着,寻找关于CPU和内存初始化的信息。关键行:你会看到类似
如果你能清晰地看到RTOS的启动日志和Linux从非0/1核心启动的日志,那么恭喜你,AMP双系统烧写并启动成功!
5. 深度调试与故障排查实录
烧写过程很少一帆风顺,尤其是涉及底层硬件划分。下面是我遇到过的几个典型问题及解决方法。
5.1 常见问题与解决方案速查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| RKDevTool无法发现设备 | 1. USB线质量差或接触不良。 2. 驱动未正确安装。 3. 按键进入Loader模式操作不对。 4. 板子硬件故障。 | 1.更换一根优质的Type-C数据线,这是最高频的原因。 2. 重新安装 DriverAssitant驱动,以管理员身份运行安装程序,安装后重启电脑。3. 严格遵循“断电 -> 按住键 -> 连USB -> 上电 -> 松键”顺序,多试几次。 4. 换一台电脑或USB端口试试。 |
| 烧写过程中失败,报错“Download Boot Fail” | 1. 镜像文件损坏或不兼容。 2. 板载eMMC芯片有坏块或物理损坏。 3. 供电不稳定。 | 1. 重新下载镜像,并校验哈希值。 2. 尝试对eMMC进行“擦除Flash”操作,如果连擦除都失败,则硬件故障可能性大。 3. 使用原装电源适配器,确保供电电压电流充足。 |
| 烧写成功,但系统无法启动,串口无输出 | 1. 串口线连接错误或波特率不对。 2. 镜像本身启动逻辑有问题。 3. 核心或内存划分与硬件不符。 | 1. 检查TX/RX是否接反,确认波特率为1500000。 2. 烧回官方的普通Linux镜像,测试板子基础功能是否正常。 3.重点:检查U-Boot环境变量。在U-Boot命令行中,用 printenv查看bootargs和bootcmd。确保bootargs中的mem=参数为Linux预留了正确的内存大小(例如总内存减去RTOS预留部分)。 |
| Linux能启动,但RTOS无启动日志 | 1. RTOS镜像未正确烧入rtos分区。2. RTOS的串口输出未启用或引脚映射错误。 3. U-Boot跳转地址错误。 | 1. 用RKDevTool的“高级功能”单独读取rtos分区内容,与原始bin文件对比。2. 查阅RTOS源码配置,确认调试串口(通常是UART2)已初始化,并且引脚复用配置与板级设计一致。 3. 在U-Boot源码或配置中,确认 CONFIG_SPL_RTOS_LOAD_ADDR等宏定义的值与镜像中RTOS的链接地址一致。 |
| 系统启动后运行不稳定,随机死机 | 1. 内存冲突。两个系统访问了同一块物理内存。 2. 中断冲突。两个系统配置了相同的中断源。 3. 缓存一致性(Cache Coherency)问题。 | 1.这是AMP调试最复杂的问题。必须严格审查RTOS和Linux的设备树/内存映射文件,确保预留内存区域(reserved-memory节点)定义完全一致且无重叠。2. 在Linux设备树中,将分配给RTOS的外设节点状态设置为 disabled。在RTOS中,明确初始化它要用的外设。3. 对于共享内存通信区域,确保双方都将其映射为非缓存(Non-cacheable)属性,或者在使用前后执行缓存清洗(cache flush/invalidate)操作。 |
5.2 进阶调试技巧:使用JTAG与日志分析
当问题比较隐蔽时,需要更强大的工具。
- JTAG调试器:这是终极武器。通过JTAG接口(RK3568通常为SDMMC_DET引脚复用),可以连接仿真器(如J-Link),在RTOS启动之初就进行单步调试,查看寄存器状态,精准定位是卡在了内存访问错误、中断向量表错误还是其他异常。这对于调试RTOS侧的启动故障无可替代。
- 系统日志分析:
- Linux侧:使用
dmesg命令查看完整内核日志,关注其中关于reserved-memory的初始化信息,以及是否有内核访问非法地址的报错(Unable to handle kernel paging request)。 - RTOS侧:如果RTOS支持,尽可能在其代码中增加不同等级的日志输出(通过串口)。将关键函数入口、出口、共享内存读写操作都打上日志,可以清晰地看到执行流在哪里中断。
- Linux侧:使用
5.3 个人踩坑心得:电源与接地的教训
分享一个我花了整整两天才解决的诡异问题。在一次烧写后,系统偶尔能启动,大部分时间串口只有乱码。排查了软件所有环节都没问题。最后用示波器测量板子的电源轨,发现3.3V电源上有频繁的、幅度不小的毛刺。原来是使用的开关电源适配器老化,输出噪声过大。同时,我的调试桌面上铺了防静电胶垫,但电脑、开发板、示波器的地线并未良好共地,形成了地环路,引入了干扰。解决方案:更换了一个优质的线性电源实验室电源,并用一根导线将开发板的GND测试点与电脑机箱外壳直接连接,确保共地。此后烧写和运行再未出现乱码或随机死机。
所以,给嵌入式开发板,尤其是运行复杂AMP系统的板子供电,一定要干净、稳定。一个嘈杂的电源,足以让一切精妙的软件设计变得不可预测。
6. 从烧写到开发:AMP系统的下一步
成功烧写并启动AMP镜像,只是一个开始。接下来,你将进入更具挑战也更有趣的阶段:双系统协同开发。
- 通信机制实现:你需要编写代码,实现RTOS与Linux之间的数据交换。RK3568通常支持基于共享内存的邮箱中断。你需要:
- 在内存保留区域划出一小块作为“邮箱缓冲区”。
- 配置好双方的中断触发机制(例如,Linux写数据后触发RTOS的中断,反之亦然)。
- 设计一套简单的协议,定义数据包格式、命令字和确认机制。
- 外设资源划分:明确哪些传感器、执行器归RTOS管,哪些归Linux管。例如,将伺服电机驱动、高精度ADC采样放在RTOS侧以保证时序;将摄像头、显示屏、网络交给Linux侧。
- 独立编译与集成:你需要建立两个独立的编译环境:一个用于编译RTOS(如ARM GCC工具链),一个用于编译Linux内核和驱动。修改任何一方的代码后,都需要重新生成其镜像文件,然后使用
rkbin工具或迅为提供的打包脚本,将U-Boot、RTOS镜像、Linux内核、根文件系统重新打包成一个新的.img文件,再进行烧写测试。
这个过程就像在设计和调试一个微型的分布式系统,硬件是共享的,但软件世界是割裂的。每一次成功的通信,都意味着你对硬件和软件的理解又深了一层。给iTOP-3568烧写AMP镜像,是打开这扇大门的第一把钥匙。希望这份超详细的手册,能帮你稳稳地握住它。