
在 xilinx mpsoc 平台上进行 Linux 软件开发,不可避免的会涉及到 PS 与 PL 之间的数据交互。这个系列介绍一种基于 DDR 的信息交互方式。
这篇文章首先介绍下如何从系统中“偷”内存。
交互流程:

3. reserved memory
如果 PS 与 PL 要基于 DDR 进行交互,那么,在 PS 端必须将内存空间从系统中“拿”出来,让系统无法知晓或无法使用这个空间。然后,应用程序要想办法操作 DDR 的物理地址进行数据读写。 如何做呢?需要借助预留内存。实现预留内存的简单方法是在设备树中增加 reserved-memory 设备节点,在该节点中定义预留内存的起始地址及大小。
比如,我要使用一块内存空间作为 PS 与 PL 信息交互的空间,该空间以 0x30000000 为起始地址,大小为 256MB。那么可以在设备树中定义如下节点信息。
project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi:
- /include/ "system-conf.dtsi"
- / {
- reserved-memory {
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- buffer@0x30000000 {
- no-map;
- reg = <0 0x30000000 0 0x10000000>;
- };
- };
- }
按照上述方式修改设备树并编译内核,系统启动后通过命令 cat /proc/iomem 即可查看系统的内存分配:
cat /proc/iomem
从下图中可以看到系统使用的内存空间被分为了两部分,0~0x2fffffff 和 0x40000000~0x7fefffff。中间丢失的部分 0x30000000~0x3fffffff 即为我们的预留内存。

如果需要预留多块内存,可以添加多个节点。比如预留两块 256MB 的空间,起始地址分别是 0x30000000 和 0x50000000,如下:
- /include/ "system-conf.dtsi"
- / {
- reserved-memory {
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- res1:buffer@0x30000000 {
- no-map;
- reg = <0 0x30000000 0 0x10000000>;
- };
- res2:buffer@0x50000000 {
- no-map;
- reg = <0 0x50000000 0 0x10000000>;
- };
- };
- };
从下图中可以看到,0x30000000~0x3fffffff 和 0x50000000~0x5fffffff 这两个地址空间系统无法使用。
基于 DDR 的 PS 与 PL 交互,PS 需要操作 DDR 的物理地址。此时就需要通过预留内存的手段让 Linux 无法使用进行交互的空间。那么,如何在用户空间中使用这块内存呢?答案是借助 UIO。

