Использование mmap на Zynq 7000 - PullRequest
0 голосов
/ 25 февраля 2019

Я хочу проверить межпроцессорное взаимодействие с использованием разделяемой памяти между программным ядром Microblaze и процессорами Zynq A9 ARM под управлением Linux на плате Zed.

В дереве устройств я зарезервировал часть памяти:

   reserved-memory {
      #address-cells = <1>;
      #size-cells = <1>;
      ranges;

      mb_shared_mem: buffer@0x10000000 {
         no-map;
         reg = <0x10000000 0x0e000000>;
      };
   };

   reserved-driver@0 {
      compatible = "xlnx,reserved-memory";
      memory-region = <&mb_shared_mem>;
   };
  1. Плата Zed имеет оперативную память 512 МБ.Если я зарезервирую верхние 256 МБ, Linux не запустится.Зачем?Это работает, когда я уменьшаю сумму до 0x0e000000

  2. Нужно ли использовать 'no-map'?Ядро не должно использовать память, но я хочу иметь доступ к ней, используя mmap.

Я создал простую тестовую программу для mmap.Программа записывает побайтовый файл в область памяти, отображаемую с помощью mmap:

int write_file( char *argv[]) {
    int fd, fd_in;

    off_t size;
    off_t file_index;

    char* fname = 0;
    char* addr = argv[3];

    fname = argv[2];


    fd_in = open(fname, O_RDONLY);
    if (fd_in < 1) {
        printf("Unable to open input file %s\n",fname );
    }

    void* load_address = (void*)strtoul(addr, NULL, 16);
    printf("Loading at address %p\n ",load_address);

    fd = open("/dev/mem", O_RDWR | O_SYNC);

    if (fd < 1) {
        printf("Unable to open mem device file\n");
        close(fd_in);
        return -1;
    }

    // determine size
    size = lseek(fd_in, 0L, SEEK_END);
    lseek(fd_in, 0L, SEEK_SET);

    printf("Copying %ld bytes\n", size);


    base_address = mmap(load_address, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_UNINITIALIZED | MAP_FIXED, fd, 0);
    if (base_address == MAP_FAILED) {
        printf("mmap failed! %s\n", strerror(errno));
        close(fd);
        close(fd_in);
        return -1;
    }


    for (file_index = 0; file_index < size; file_index++) {
        uint8_t file_byte;
        ssize_t result = read(fd_in, &file_byte,1);

        if (result<0) {
            printf("Error during fileread: %s", strerror(errno));
            break;
        }
        base_address[file_index] = file_byte;

        if (base_address[file_index] != file_byte) {
            printf("Write failed, offset %lx failed\n", file_index);
            break;
        }
        if ((file_index % 100) == 0) {
            printf(".");
        }
    }
    printf("\n");

    munmap(base_address, size);
    close(fd_in);
    close(fd);
    return 0;
}

В большинстве примеров, которые я нашел, я вижу:

mmap (NULL, размер, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_UNINITIALIZED | MAP_FIXED, fd, load_address);

Почему бы не указать физический адрес в качестве первого аргумента и 0 в качестве смещения (последнего аргумента)?

Размер страницы системы составляет 4096 байт.Если я использую функцию для записи файла размером 2890 байт, функция возвращается без ошибок.С файлом размером 60000 байт ядро ​​зависает / вылетает.

Я также написал программу для чтения памяти с использованием mmap.Я попытался сделать следующее:

записать 2980 байтов файла_A в 0x1000_0000

записать 2980 байтов файла_B в 0x1200_0000

прочитать 2980 байтов0x1000_0000> file_A_tst

чтение 2980 байтов 0x1200_0000> file_B_tst

При проверке содержимого прочитанных файлов я вижу, что file_A_tst равно file_B_tst и file_B.Таким образом, кажется, что записанная отображенная память фактически не сбрасывается в физическую память? Я просто получаю старые данные из предыдущего mmap. Мне нужно использовать MAP_UNINITIALIZED, потому что я не хочу, чтобы Linux очищал физическую память.

...