zynq에서 정렬되지 않은 메모리에 액세스할 때 버스 오류

zynq에서 정렬되지 않은 메모리에 액세스할 때 버스 오류

편집: 이것을 더 나은 스택 교환 사이트에 올려야 합니까?

저는 특히 Xilinx 개발 보드 zcu102에서 zynq 하이퍼스케일 칩의 FPGA 측에 연결된 DDR4를 사용하려고 합니다. 저는 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 

플래그의 차이점이 무슨 일이 일어나고 있는지 설명하는지 잘 모르겠지만 메모리 매핑에 더 정통한 사람이 뭔가를 알고 있는 경우를 대비해 포함시키고 있습니다.

관련 정보