在 zynq 上访问非对齐内存时出现总线错误

在 zynq 上访问非对齐内存时出现总线错误

编辑:我应该把它放在一个更好的 stackexchange 网站上吗?

我正在尝试使用连接到 zynq 超大规模芯片的 FPGA 端的 DDR4,特别是在 Xilinx 的开发板 zcu102 上。我正在使用 Vivado 的 MIG 生成控制器并连接到主处理器的 HPM0 AXI 端口。内存长度为0x2000_0000,映射到物理地址0x4_0000_0000。

我遇到的问题是访问未对齐的内存时。我认为这是由于设备树中缺少细节而导致 MMU 中的一些配置错误。

我知道的一件事是,这个手臂(A53)应该能够在必要时将未对齐的访问转变为对内存的多次访问。我收到总线错误告诉我 MMU 在某种程度上配置错误,但我不确定如何配置。

设备树太长,放在这里,所以我将我认为最重要的部分直接放在这里,其余的作为帕斯特宾

    amba_pl@0 {
            #address-cells = <0x2>;
            #size-cells = <0x2>;
            compatible = "simple-bus";
            ranges;

            ddr4@400000000 {
                    compatible = "xlnx,ddr4-2.2";
                    reg = <0x4 0x0 0x0 0x20000000>;
                    alignment = <0x10>;
            };

            PERIPHERAL@ff380000 {
                    compatible = "xlnx,PERIPHERAL-1.0";
                    reg = <0x0 0xff380000 0x0 0x80000>;
            };

            PERIPHERAL@ff990000 {
                    compatible = "xlnx,PERIPHERAL-1.0";
                    reg = <0x0 0xff990000 0x0 0x10000>;
            };
    };

    aliases {
            ethernet0 = "/amba/ethernet@ff0e0000";
            i2c0 = "/amba/i2c@ff020000";
            i2c1 = "/amba/i2c@ff030000";
            serial0 = "/amba/serial@ff000000";
            serial1 = "/amba/serial@ff010000";
            spi0 = "/amba/spi@ff0f0000";
    };

    memory {
            #address-cells = <0x2>;
            #size-cells = <0x2>;
            device_type = "memory";
            alignment = <0x10>;
            reg = <0x4 0x0 0x0 0x20000000>;
    };

我尝试在 /memory 和 /amba_pl 上的 ddr 控制器上设置对齐方式,但似乎没有什么区别。事实上,它似乎忽略了 /memory 部分,因为它仍然从主系统内存而不是 fpga 上的内存启动。

我可以使用 mmap 和 devmem 访问内存,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>

#define ARRAY_TYPE uint16_t

int main(int argc, char *argv[]) {
    if (argc != 2){
        printf("Wrong arg count\n");
        return -1;
    }
    volatile ARRAY_TYPE * ps = malloc(sizeof(ARRAY_TYPE)*10);
    if (NULL==ps){
        printf("Failed to malloc for ps\n");
        return -1;
    }


    int fd = open("/dev/mem", O_RDWR | O_SYNC );
    volatile ARRAY_TYPE *pl = mmap((void*)0x400000000, 0x20000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x400000000);
    if (pl == MAP_FAILED) {
        perror("Can't map memory for pl");
        printf("FAIL\n");
        return -1;
    }


    //force them out of alignment by argv[1] bytes.
    volatile ARRAY_TYPE *ps_unaligned = (volatile ARRAY_TYPE *)(((uint8_t *)ps) + atoi(argv[1]));
    volatile ARRAY_TYPE *pl_unaligned = (volatile ARRAY_TYPE *)(((uint8_t *)pl) + atoi(argv[1]));

    printf("trying ps with offset %d\n", atoi(argv[1]));
    ps_unaligned[0] = 1;
    printf("trying pl with offset %d\n", atoi(argv[1]));
    pl_unaligned[0] = 1;

    munmap(pl, 0x20000000);
    free(ps);
    close(fd);

    return 0;
}

每当我尝试访问与主系统内存不对齐的内存时,它都可以正常工作。然而,当我访问悬挂在未对齐的 FPGA 上的内存时,会出现总线错误。

root@zynq: ~
17:22:08 $ ./memtest 0
trying ps with offset 0
trying pl with offset 0
root@zynq: ~
17:22:12 $ ./memtest 1 
trying ps with offset 1
trying pl with offset 1
Bus error
root@zynq: ~
17:22:13 $ ./memtest 2
trying ps with offset 2
trying pl with offset 2
root@zynq: ~
17:22:14 $ ./memtest 3
trying ps with offset 3
trying pl with offset 3
Bus error

我还通过在 gdb 会话期间查看 /proc/$pid/smaps 来查看内存区域的虚拟内存映射:这是包含使用 devmem/mmap 分配的系统内存的部分:

400000000-420000000 rw-s 400000000 00:06 1054                            /dev/mem
Size:             524288 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr sh mr mw me ms pf io de dd 

以下是从 FPGA 映射的内存部分:

5555567000-5555588000 rw-p 00000000 00:00 0                              [heap]
Size:                132 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Anonymous:             4 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr mr mw me ac 

我不确定标志中的任何差异是否可以解释发生的情况,但我将它们包括在内,以防更精通内存映射的人知道一些事情。

相关内容