Перейти к содержанию
    

Всем привет! По роду своей деятельности появилась необходимость "поднимать" PCIe.

Прочитано немноло даташитов и прочих талмудов. Собираюсь тут задавать вопросы по данной теме и внимательно слушать советы...

Вводные данные: Плата на базе Xilinx Kintex UltraScale, PCIe Gen 3.0 x8, Vivado 2018.1

Первое, что я сделал сконфигурировал IP-блок UltraScale FPGA Gen3 Integrated Block for PCI Express. Сразу появилась нужна знать - как выглядит конфигурационное пространство, полученного IP-блока PCIe? (Данная информация нужна будет для тех, кто будет писать драйвер для ПК). Имеется ли возможность прочитать содержимое конфигурационного пространства (хотя бы ту часть, которую не трогает ОС) без непосредственного подлючения платы в слот ПК? Например, может в процессе генерации IP-блока создается некоторый файл или я могу это сделать через какой-либо интерфейс полученного IP-блока?

Заранее, спасибо!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, dde29 said:

Сразу появилась нужна знать - как выглядит конфигурационное пространство, полученного IP-блока PCIe?

Как выглядит  это пространство показано в UG на эту корку.  А возможность читать это пространство есть как со стороны самого PCIe  так и изнутри FPGA  через cfg_* интерфейс насколько я это помню.    
Ну а без подключения к ПК проще  всего начать работать с коркой это запустить симуляцию оной.  Тогда будет доступно делать с коркой все тоже что и в ПК, но естественно это все будет медленно.   

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы в линуксе просто стартануть драйвер и подцепить железяку, для начала из конфига нужен просто VID и DID, они есть в самой корке.
Чтобы просто стартануть PCIE чисто проверить, без драйвера командой lspci, конфиг на этом этапе пока не нужен

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, new123 said:

Чтобы в линуксе просто стартануть драйвер и подцепить железяку

Даже  больше  - Linux (как и обычно др. ОС) уже имеет в себе стандартный драйвер PCIe который собственно и работает со стандартным конфигурационным пространством каждого PCIe девайса в системе.  И lspci как раз через этот драйвер работает. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По работе поднимал PCIe на  Xilinx Kintex 7 и UltraScale, IP блок DMA/Bridge Subsystem for PCI Express  https://www.hackster.io/Roy_Messinger/pci-express-with-dma-sub-system-241d15, под Виндой использовал Xilinx Answer 65444 Xilinx PCI Express Windows DMA Drivers and Software Guide, ставил драйвер xdma, на основе исходников их утилиты писал свой драйвер, под Линухом то же самое. 

Изменено пользователем ovn

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/20/2022 at 3:46 PM, RobFPGA said:

Как выглядит  это пространство показано в UG на эту корку.  А возможность читать это пространство есть как со стороны самого PCIe  так и изнутри FPGA  через cfg_* интерфейс насколько я это помню.    
Ну а без подключения к ПК проще  всего начать работать с коркой это запустить симуляцию оной.  Тогда будет доступно делать с коркой все тоже что и в ПК, но естественно это все будет медленно.   

Да, как выглядит пространство известно. Т.е. имеется возможность прочитать содержимое конфигурационного пространства через (как я понял) интерфейс:

  cfg_mgmt_addr,
  cfg_mgmt_write,
  cfg_mgmt_write_data,
  cfg_mgmt_byte_enable,
  cfg_mgmt_read,
  cfg_mgmt_read_data,
  cfg_mgmt_read_write_done,
  cfg_mgmt_type1_cfg_reg_access

Только вот, у меня мозг так устроен, что лучше всего обмен данными устроен через изучение временных диаграмм, коих по данной теме почти нет (ну или мне было не по глазам). Буду Разбираться, благодарю!

Да, есть вариант запустить симуляцию, но тут меня кидает в холодный пот. Причина - я раньше работал только с продуктами Altera/Intel? поэтому переход на Вивадо происходит у меня болезненно. Но, хныкать не будем, тоже буду копать в этом направлении!

 

On 9/20/2022 at 4:04 PM, new123 said:

Чтобы в линуксе просто стартануть драйвер и подцепить железяку, для начала из конфига нужен просто VID и DID, они есть в самой корке.
Чтобы просто стартануть PCIE чисто проверить, без драйвера командой lspci, конфиг на этом этапе пока не нужен

VID и PID, согласен известны уже в самой корке, и также, да, в Линуксе добился того, что ОС подружилась с платой, а значит корка по минимальным настройкам сконфигурирована верно (через lspci распознается как надо).

Для того, чтобы начать писать драйвер, согласен достаточно VID PID, но в дальнейшем нужно чтобы корка как-то отвечала на посылки с хоста на плату. Как я понимаю, для этого нужно изучить интерфейс AXI4-Stream (вроде простой). Только вопрос:

Посылку от хоста я (мой user code на ПЛИС) могу получить на интерфейсе Completer Request, в ответ мне нужно будет сформировать пакет на интерфейсе Completer Completion. Подскажите, я правильно понимаю данный процесс "запрос/ответ" в контексте простого взаимодействия хост-девайс ?

On 9/20/2022 at 4:12 PM, RobFPGA said:

Даже  больше  - Linux (как и обычно др. ОС) уже имеет в себе стандартный драйвер PCIe который собственно и работает со стандартным конфигурационным пространством каждого PCIe девайса в системе.  И lspci как раз через этот драйвер работает. 

А через этот стандартный драйвер каким образом можно реализовать простейший обмен данными между ОС и платой - через какие рычаги? В каком направлении мне тут покопать?

On 9/20/2022 at 6:00 PM, ovn said:

По работе поднимал PCIe на  Xilinx Kintex 7 и UltraScale, IP блок DMA/Bridge Subsystem for PCI Express  https://www.hackster.io/Roy_Messinger/pci-express-with-dma-sub-system-241d15, под Виндой использовал Xilinx Answer 65444 Xilinx PCI Express Windows DMA Drivers and Software Guide, ставил драйвер xdma, на основе исходников их утилиты писал свой драйвер, под Линухом то же самое. 

 

Спасибо! Поизучаю инфу по Вашим ссылкам!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/20/2022 at 2:00 PM, ovn said:

По работе поднимал PCIe на  Xilinx Kintex 7 и UltraScale, IP блок DMA/Bridge Subsystem for PCI Express  https://www.hackster.io/Roy_Messinger/pci-express-with-dma-sub-system-241d15, под Виндой использовал Xilinx Answer 65444 Xilinx PCI Express Windows DMA Drivers and Software Guide, ставил драйвер xdma, на основе исходников их утилиты писал свой драйвер, под Линухом то же самое. 

 

Добрый день. Подскажите почему писали свой драйвер, а не использовали xdma?

Как потом устанавливали драйвер без подписи?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/21/2022 at 12:20 PM, dtmf73 said:

Добрый день. Подскажите почему писали свой драйвер, а не использовали xdma?

Как потом устанавливали драйвер без подписи?

Здравствуйте! Драйвер еще не написан, им только занялись, причем не лично я (я плисовод и цифровик-железячник), а другой отдел программистов.

По поводу xdma - могу уточнить...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 hours ago, dde29 said:

Для того, чтобы начать писать драйвер, согласен достаточно VID PID, но в дальнейшем нужно чтобы корка как-то отвечала на посылки с хоста на плату. Как я понимаю, для этого нужно изучить интерфейс AXI4-Stream (вроде простой). Только вопрос:

надо определиться какой механизм задействовать. Или DMA или BAR.

BAR для пробы в разы проще, но подходит для малых пересылок, примерно до 64байт, дальше выигрывает DMA. 
Из драйвера пишем в BAR (если доступ нужен из user space, то пишем в файл /bus/pci/../resourceX

Потом это дело на нужном AXI читаем

В обратную сторону так же.

Изменено пользователем new123

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/21/2022 at 6:34 PM, new123 said:

надо определиться какой механизм задействовать. Или DMA или BAR.

BAR для пробы в разы проще, но подходит для малых пересылок, примерно до 64байт, дальше выигрывает DMA. 
Из драйвера пишем в BAR (если доступ нужен из user space, то пишем в файл /bus/pci/../resourceX

Потом это дело на нужном AXI читаем

В обратную сторону так же.

 

Для первого этапа - достаточно BAR, так как необходимо просто обмен медленными посылками между ПЛИС на плате и ПК.

Для второго этапа, скорее всего да - придется задействовать механизм DMA...

Изменено пользователем dde29

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 21.09.2022 в 08:20, dtmf73 сказал:

Добрый день. Подскажите почему писали свой драйвер, а не использовали xdma?

Как потом устанавливали драйвер без подписи?

В Винде устанавливал драйвер xdma от Xilinx, он без цифровой подписи, с драйвером работал из Microsoft Visual Studio, на основе исходников их утилиты писал свой "драйвер", на низшем уровне там, хоть в Линухе, хоть в Винде работа с устройством xdma, как с файлом(пишем в файл, читаем из файла), ну и соответственно уже на более верхнем уровне писал драйвер для своей конкретной железки, обращение к её регистрам и DDR и т.д. 

Изменено пользователем ovn

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного запутался в принципах интерфейса AXI4-Stream. Основными интерфейсам взаимодействия хоста и user logic через IP-блок являются:
Completer Requester Interface (AXI4-Stream Master)
Completer Completion Interface (AXI4-Stream Slave)
Requester Requester Interface (AXI4-Stream Slave)
Requester Completion Interface (AXI4-Stream Master)

Насколько я понял, изучая документ PG156, взаимодействие между хостом и user logic происходит следующим образом:
1.1 Если хост инициирует передачу пакета - данные появятся на линиях интерфейса Completer Requester
1.2 В ответ на принятый пакет user logic отдает ответный пакет (а может и не отдавать) на линии интерфейса Completer Completion Interface
2.1 Если же user logic инициирует передачу пакета на хост, то это необходимо сделать через линии интерфейса Requester Requester Interface
2.2 В ответ хост может ответить посылкой на линии Requester Completion Interface

Правильно ли я понял процесс обмена данными?

AXI4-Stream.JPG

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не хочется ломать голову - возьмите ядро AXI Bridge for PCI Express. В нем можно просто писать по адресам, а не вручную формировать очереди запросов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите пожалуйста по следующей проблеме:

 Использую XDMA на Kintex девките. Девкит в свою очередь подключен к Jetson TX2 девкиту. Создал простой AXI4 Lite Slave на 4 регистра. Slave прошел через SV AXI4 BFM тест, использвал готовый который генерит Vivado. Подключен он к 32бит BAR 0, выделен 1МБ.

Работаю с Ubuntu, использовал софт по моему автора туториала по XDMA . Получается запись и чтение регистров ведется из user space, а не из ядра линукса. Могут ли быть какие то проблемы с этим? Получается только 1 раз записать и считать определенное значение, далее чтение показывает 0.

sudo ./pcie_test /sys/bus/pci/devices/0000\:01\:00.0/resource0 0x00000000 w 0xDEADAB

Пока разбираюсь с System ILA, посмотреть что реально просходит на шине. Железо на несколько дней недоступно, хотелось бы понять есть ли риск в том что чтение/запись в регистры из user space на самом деле не работает всегда корректно?

 


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <linux/pci.h>


#define PRINT_ERROR \
    do { \
        fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
        __LINE__, __FILE__, errno, strerror(errno)); exit(1); \
    } while(0)

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {
    int fd; 
    void *map_base, *virt_addr;
    uint32_t read_result, writeval;
    char *filename;
    off_t target;
    int access_type = 'w';

    if(argc < 3) {
        // pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0 0x100 w 0x00
        // argv[0]  [1]                                         [2]   [3] [4]
        fprintf(stderr, "\nUsage:\t%s { sys file } { offset } [ type [ data ] ]\n"
                "\tsys file: sysfs file for the pci resource to act on\n"
                "\toffset  : offset into pci memory region to act upon\n"
                "\ttype    : access operation type : [b]yte, [h]alfword, [w]ord\n"
                "\tdata    : data to be written\n\n",
                argv[0]);
        exit(1);
    }   
    filename = argv[1];
    target = strtoul(argv[2], 0, 0); 

    if(argc > 3)
        access_type = tolower(argv[3][0]);

    if((fd = open(filename, O_RDWR | O_SYNC)) == -1){
        PRINT_ERROR;
    }
    printf("%s opened.\n", filename);
    printf("Target offset is 0x%x, page size is %ld map mask is 0x%lX\n", (int) target, sysconf(_SC_PAGE_SIZE), MAP_MASK);
    fflush(stdout);

    /* Map one page */
#if 0
    //map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) (target & ~MAP_MASK));
    //map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
#endif
    printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (target & ~MAP_MASK));
    if(map_base == (void *) -1){
       printf("PCI Memory mapped ERROR.\n");
        PRINT_ERROR;
        close(fd);
        return 1;
    }

    printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));
    printf("PCI Memory mapped %ld byte region to map_base 0x%08lx.\n", MAP_SIZE, (unsigned long) map_base);
    fflush(stdout);

    virt_addr = map_base + (target & MAP_MASK);
    printf("PCI Memory mapped access 0x %08X.\n", (uint32_t ) virt_addr);
   switch(access_type) {
        case 'b':
                read_result = *((uint8_t *) virt_addr);
                break;  
        case 'h':
                read_result = *((uint16_t *) virt_addr);
                break;  
        case 'w':
                read_result = *((uint32_t *) virt_addr);
                        printf("READ Value at offset 0x%X (%p): 0x%X\n", (int) target, virt_addr, read_result);
                break;
        default:
                fprintf(stderr, "Illegal data type '%c'.\n", access_type);
                exit(2);
    }
    fflush(stdout);

    if(argc > 4) {
        writeval = strtoul(argv[4], 0, 0);
        switch(access_type) {
                case 'b':
                        *((uint8_t *) virt_addr) = writeval;
                        read_result = *((uint8_t *) virt_addr);
                        break;
                case 'h':
                        *((uint16_t *) virt_addr) = writeval;
                        read_result = *((uint16_t *) virt_addr);
                        break;
                case 'w':
                        *((uint32_t *) virt_addr) = writeval;
                        read_result = *((uint32_t *) virt_addr);
                        break;
        }
        printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
        fflush(stdout);
    }

    if(munmap(map_base, MAP_SIZE) == -1) { PRINT_ERROR;}
    close(fd);
    return 0;
}

 

Изменено пользователем alxkon

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще один момент, который я обнаружил, непонятный мне:

сконфигурировав IP-блок UltraScale FPGA Gen3 Integrated Block for PCI Express, я должен был получить user_clock частотой 250 МГц, согласно настройкам корки... Вывед данный клок наружу ПЛИС - осциллом наблюдаю 25 Мгц (да, я не гоню, ноликом не ошибься :acute: ). Как можно это объяснить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...