在嵌入式系统开发中,非对称多处理(AMP)架构因其能够同时兼顾通用计算和实时响应的特性,正逐渐成为工业控制、智能家居等领域的首选方案。本文将基于Rockchip RK3562芯片,手把手带你完成Linux与RT-Thread双系统AMP环境的搭建,涵盖从内存划分、外设分配到RPMsg通信的全套实战细节。
RK3562作为一款典型的异构多核处理器,包含四核Cortex-A53和一个Cortex-M0核心,为AMP架构提供了理想的硬件基础。在开始前,我们需要明确几个关键概念:
开发环境搭建需要以下组件:
bash复制# 基础工具链
sudo apt-get install gcc-aarch64-linux-gnu gcc-arm-none-eabi
# RK3562专用编译工具
wget https://repo.rock-chips.com/rk3562/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
内存划分是AMP系统稳定的基石。RK3562的DDR控制器支持多区域配置,我们需要在Linux设备树中明确划分各核心的专属区域。
修改rk3562-amp.dtsi中的reserved-memory节点:
dts复制reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* RT-Thread专用区域 (1MB) */
mcu_reserved: mcu@7b00000 {
reg = <0x0 0x7b00000 0x0 0x100000>;
no-map;
};
/* RPMsg共享内存 (4MB) */
rpmsg_reserved: rpmsg@7c00000 {
reg = <0x0 0x07c00000 0x0 0x400000>;
no-map;
};
/* 核间通信DMA缓冲区 (1MB) */
rpmsg_dma_reserved: rpmsg-dma@8000000 {
compatible = "shared-dma-pool";
reg = <0x0 0x08000000 0x0 0x100000>;
no-map;
};
};
关键参数说明:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| no-map | 阻止Linux映射该区域 | 必须设置 |
| reg | 物理地址和大小 | 按实际调整 |
| compatible | 特殊内存类型标识 | shared-dma-pool需特殊声明 |
当出现随机崩溃时,可通过以下命令检查内存冲突:
bash复制# 查看Linux内存映射
cat /proc/iomem | grep -A 20 "reserved"
# 检查RT-Thread内存使用
rt_memcheck
常见问题解决方案:
uncachedRK3562的外设资源需要在两个系统间明确划分,避免访问冲突。以下以I2C1和UART2为例展示配置方法。
在最终使用的设备树文件(如rk3562-evb.dts)中关闭需要分配给RT-Thread的外设:
dts复制&i2c1 {
status = "disabled";
};
&uart2 {
status = "disabled";
};
在RT-Thread的BSP中配置对应外设:
c复制// board/iomux.c
void rt_hw_iomux_config(void)
{
/* I2C1引脚复用 */
HAL_PINCTRL_SetIOMUX(GPIO_BANK0,
GPIO_PIN_B3 | GPIO_PIN_B4,
PIN_CONFIG_MUX_FUNC1);
/* UART2引脚配置 */
HAL_PINCTRL_SetIOMUX(GPIO_BANK0,
GPIO_PIN_A0 | GPIO_PIN_A1,
PIN_CONFIG_MUX_FUNC2);
}
外设分配注意事项:
使用AMP专用配置编译RT-Thread:
bash复制export RTT_ROOT=/path/to/rt-thread
export BSP_ROOT=$RTT_ROOT/bsp/rockchip/rk3562-mcu
scons --menuconfig # 开启RPMSG和所需外设驱动
scons -j8
./mkimage.sh # 生成amp.img
配置Linux内核支持AMP和RPMsg:
bash复制make ARCH=arm64 rockchip_linux_defconfig
# 开启以下配置选项:
CONFIG_MAILBOX=y
CONFIG_ROCKCHIP_MBOX=y
CONFIG_RPMSG_ROCKCHIP_MBOX=y
CONFIG_RPMSG_VIRTIO=y
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j8
使用RK官方工具按顺序烧录各组件:
烧录完成后,通过串口可观察到双系统启动日志:
code复制[RT-Thread] mcu core started
[Linux] Booting Linux on physical CPU 0x0
RPMsg作为AMP系统的通信桥梁,其配置和使用需要特别注意以下要点。
确保设备树包含正确的rpmsg节点:
dts复制&rpmsg {
rockchip,link-id = <0x04>; /* M0核心标识 */
memory-region = <&rpmsg_reserved>;
};
在RT-Thread中初始化RPMsg端点:
c复制#define RPMSG_REMOTE_ADDR 0x4004
struct rpmsg_lite_instance *rpmsg;
rpmsg = rpmsg_lite_remote_init((void*)0x7c00000,
RL_PLATFORM_SET_LINK_ID(0, 4),
RL_NO_FLAGS);
rpmsg_lite_create_ept(rpmsg, RPMSG_REMOTE_ADDR,
rpmsg_endpoint_cb, NULL);
Linux端发送数据:
c复制int fd = open("/dev/rpmsg0", O_RDWR);
write(fd, "ping", 4);
read(fd, buf, sizeof(buf)); // 读取响应
RT-Thread端接收处理:
c复制static int rpmsg_endpoint_cb(void *payload, uint32_t len,
uint32_t src, void *priv)
{
rt_kprintf("Received: %s\n", (char*)payload);
rpmsg_lite_send(rpmsg, ept, src, "pong", 4, RL_BLOCK);
return 0;
}
性能优化技巧:
| 优化方向 | 方法 | 效果 |
|---|---|---|
| 延迟优化 | 使用mailbox代替软中断 | 降低50%延迟 |
| 吞吐量 | 增大vring缓冲区 | 提升30%带宽 |
| 稳定性 | 添加CRC校验 | 提高可靠性 |
症状1:RT-Thread启动后Linux卡死
症状2:RPMsg通信失败
/sys/kernel/debug/rpmsg目录下的端点信息Linux端:
bash复制# 监控Mailbox中断频率
cat /proc/interrupts | grep mailbox
# 查看RPMSG负载
cat /sys/kernel/debug/rpmsg/stats
RT-Thread端:
c复制// 添加性能监控钩子函数
void rpmsg_perf_monitor(void)
{
static rt_uint32_t last_cnt;
rt_uint32_t current = rpmsg_get_tx_cnt();
rt_kprintf("Throughput: %d msg/s\n", current - last_cnt);
last_cnt = current;
}
在完成基础功能验证后,可以进一步优化:
write-combine通过以上步骤,我们已经在RK3562上成功构建了一个稳定运行的AMP系统。实际项目中,建议先从简单的GPIO通信开始验证,逐步增加复杂外设和通信协议。记得在最终产品中关闭调试输出和监控功能,以获得最佳性能表现。