Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Spartan6 + PCIe + DMA
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Andre7
Имееться Spartan6, на нем реализован PCIe интерфейс. Нужен пример драйвера под UBUNTU, что бы реализовать потоковое чтение. PCI- устройство посылает запрос на чтение по любому адресу оперативной памяти и в ответ должно получать TLP c длинной данных 16 DWORD. Сейчас есть драйвер, который использует метод MMAP, но на нем не удаеться получить TLP c данными больше 1DWORD.
Вопросы к теме:
1. Обязательно ли использовать DMA, что бы работать с TLP больше 1DWORD?
2. Есть ли разница между контроллером DMA на разных компьютерах?
3. По какой схеме строиться запрос DMA от PCI-устройства к компьютеру? (Какую литературу можно почитать)

Возможно у кого-нибудь есть примеры реализации подобного драйвера?
Methane
Цитата(Andre7 @ Jun 3 2013, 16:33) *
Имееться Spartan6, на нем реализован PCIe интерфейс. Нужен пример драйвера под UBUNTU, что бы реализовать потоковое чтение.

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

Цитата
PCI- устройство посылает запрос на чтение по любому адресу оперативной памяти и в ответ должно получать TLP c длинной данных 16 DWORD.

Сколько PCIe может передать данных за раз, должен сказать PCIe хост при инициализации. Может быть хост и не умеет столько.

Цитата
Сейчас есть драйвер, который использует метод MMAP, но на нем не удаеться получить TLP c данными больше 1DWORD.
Вопросы к теме:

Не понял. MMAP это метод отмапить память ядра в адресное пространство user space. К TLP он отношения не имеет совершенно.

Цитата
1. Обязательно ли использовать DMA, что бы работать с TLP больше 1DWORD?


Это ограничение процессора. Вроде как с помощью SSE можно больше чем 128 бит передать за раз.

Цитата
2. Есть ли разница между контроллером DMA на разных компьютерах?


Да. Один может прислать данные одним куском, другой по частям. Еще с кредитами может быть по разному. DMA, а точнее PCIe вообще сильно отличаются даже в пределах одного компьютера, плата может быть воткнута непосредственно в тот PCIe что из процессора идет а может быть воткнута через свич.

Цитата
3. По какой схеме строиться запрос DMA от PCI-устройства к компьютеру? (Какую литературу можно почитать)

Возможно у кого-нибудь есть примеры реализации подобного драйвера?

Вы решите что вам надо сначала PCIe или драйвер. Потому как PCIe пофиг какая ось стоит. Как PCI работает неплохо на сайте альтеры расписано, применительно к ее корке. Также на торрентах лежат книги на английском. Про драйвера и примеры, http://lwn.net/Kernel/LDD3/ все что касается PCI можно и к PCIe применять.
Andre7
Цитата(Methane @ Jun 3 2013, 20:52) *
Все что должна сделать убунта, это выделить кусок непрерывной памяти, и передать его физический адресс в корку.

Пробовал записывать в плату функцией memcpy_toio( iobase0[ADDR], &buf, 32). В итоге получаю 8 TLP каждый length=1 , потоковой записи не получается.

Цитата(Methane @ Jun 3 2013, 20:52) *
Сколько PCIe может передать данных за раз, должен сказать PCIe хост при инициализации. Может быть хост и не умеет столько.

Очень даже возможно, а как узнать сколько хост может передавать?

Цитата(Methane @ Jun 3 2013, 20:52) *
Да. Один может прислать данные одним куском, другой по частям. Еще с кредитами может быть по разному. DMA, а точнее PCIe вообще сильно отличаются даже в пределах одного компьютера, плата может быть воткнута непосредственно в тот PCIe что из процессора идет а может быть воткнута через свич.

Это получаеться лучше ставить плату как можно ближе к нуливой шине. Буду иметь ввиду.

Цитата(Methane @ Jun 3 2013, 20:52) *
Вы решите что вам надо сначала PCIe или драйвер. Потому как PCIe пофиг какая ось стоит. Как PCI работает неплохо на сайте альтеры расписано, применительно к ее корке. Также на торрентах лежат книги на английском. Про драйвера и примеры, http://lwn.net/Kernel/LDD3/ все что касается PCI можно и к PCIe применять.

С ПЛИСиной более-менее понятно, а вот с драйвером только недавно начал разбираться.
Methane
Цитата(Andre7 @ Jun 4 2013, 06:23) *
Пробовал записывать в плату функцией memcpy_toio( iobase0[ADDR], &buf, 32). В итоге получаю 8 TLP каждый length=1 , потоковой записи не получается.

А IO зачем?

Все правильно получается у вас. 32битная архитектура. Откуда может взяться потоковая запись. Тут ПЛИС должна сформировать запрос, memory read request, и комп должен ей ответить в ответ данными.

Цитата
Очень даже возможно, а как узнать сколько хост может передавать?

Он сам корке должен сказать.

Цитата
Это получаеться лучше ставить плату как можно ближе к нуливой шине. Буду иметь ввиду.

Это получается что нужно делать так чтобы работало в любом слоте. Не привязываясь к процессору, мамке, BIOSу итд.

Цитата
С ПЛИСиной более-менее понятно, а вот с драйвером только недавно начал разбираться.

А с драйвером что не понятно?
Linux/Documentation/PCI/PCI-DMA-mapping.txt
pci_alloc_consistent вызываете, получаете указать на память процессора и память физическую.
Andre7
Цитата(Methane @ Jun 4 2013, 11:42) *
А с драйвером что не понятно?
Linux/Documentation/PCI/PCI-DMA-mapping.txt
pci_alloc_consistent вызываете, получаете указать на память процессора и память физическую.


Попробовал сделать следующим образом:
Цитата
char *gReadBuffer;
dma_addr_t gReadHWAddr;
...
pci_set_dma_mask(gDev, DMA_32BIT_MASK);
pci_set_consistent_dma_mask(gDev, DMA_32BIT_MASK)
gReadBuffer = pci_alloc_consistent(gDev, BUF_SIZE, &gReadHWAddr);


Затем gReadBuffer передаю программе и записываю тестовые данные. gReadHWAddr передаю PCI устройству, и испльзую в запросе на чтение.
В итоге, если в запросе length=1, данные в ответ приходят с правильным значением. Если length>1, то ответа вообще не получаю.

Что еще я забыл сделать?

Вот что выдает lspci -vv:
Цитата
Latency: 0, Cache Line Size: 4 bytes
Region 0: Memory at fdeff000 (32-bit, non-prefetchable) [size=512]
Region 1: Memory at fdefe000 (32-bit, non-prefetchable) [size=2K]
Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [58] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited, ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupporte d- RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ MaxPayload 256 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-


MaxPayload - вроде бы должно хватать. Не понятено может ли влиять параметр Cache Line Size
Methane
Цитата(Andre7 @ Jun 4 2013, 12:12) *
Попробовал сделать следующим образом:

У меня

Код
pci_enable_device (dev)
pci_set_master (dev);
pci_request_regions (dev, "Methane");
  if (pci_set_dma_mask (dev, DMA_BIT_MASK (64)) < 0 || pci_set_consistent_dma_mask (dev, DMA_BIT_MASK (64)) < 0)
    {
      goto fail4_dma_mask;
    }
board->cpuTX0 = pci_alloc_consistent (dev, 0x10000*8, &board->phyTX0);


board->phyTX0 можно передавать в ПЛИСину.

Цитата
Затем gReadBuffer передаю программе и записываю тестовые данные. gReadHWAddr передаю PCI устройству, и испльзую в запросе на чтение.
В итоге, если в запросе length=1, данные в ответ приходят с правильным значением. Если length>1, то ответа вообще не получаю.

Что еще я забыл сделать?

Код
                TX_DMA_REQ_START:begin
                    if(pcie.tx_sel == 1'b1)begin
                        pcie.tx_req <= 1'b1;
                        //pcie.tx_dfr <= 1'b1;
                        state_tx     <= TX_DMA_WAIT_ACK;
                        
                       pcie.tx_desc[127]     <= `RESERVED_1BIT    ;
                       //pcie.tx_desc[126:125] <= (addr_now_over_4g==1'b0) ?  `TLP_FMT_3DW_R : `TLP_FMT_4DW_R;
                       pcie.tx_desc[126:125] <= `TLP_FMT_4DW_R;
                       pcie.tx_desc[124:120] <= `TLP_TYPE_READ   ;
                       pcie.tx_desc[119]     <= `RESERVED_1BIT    ;
                       pcie.tx_desc[118:116] <= `TLP_TC_DEFAULT   ;
                       pcie.tx_desc[115:112] <= `RESERVED_4BIT    ;
                       pcie.tx_desc[111]     <= `TLP_TD_DEFAULT   ;
                       pcie.tx_desc[110]     <= `TLP_EP_DEFAULT   ;
                       pcie.tx_desc[109:108] <= `TLP_ATTR_DEFAULT ;
                       pcie.tx_desc[107:106] <= `RESERVED_2BIT    ;
                       pcie.tx_desc[105:96]  <=  pcie.cfg_maxrdreq_dw[9:0];//'h40;//burst_lenght      ;
                       pcie.tx_desc[95:83]   <= pcie.cfg_busdev;//`ZERO_WORD        ;
                       pcie.tx_desc[82:80]   <= 3'h0;//`ZERO_WORD        ;
                       //pcie.tx_desc[95:80]   <= `ZERO_WORD        ;
                       pcie.tx_desc[79:72]   <= DMA_TAG[7:0];//tx_tag            ;
                       pcie.tx_desc[71:64]   <= 8'b11111111;
                       pcie.tx_desc[63:0]    <= addr_now[63:0];//(addr_now_over_4g==1'b0)?{addr_now[31:0],32'h0}:{addr_now[63:0]};
                       tx_tag <= DMA_TAG[7:0];
                    end//if(pcie.tx_sel == 1'b1)begin
                end //DMA_REQ_START:

Длинна для чтения определяется pcie.cfg_maxrdreq_dw Сколько можно запросить данных столько оно и запрашивает.

Да, а запрос у вас выровнен по странице? burst не может пересекать page в 4к
Andre7
Ура, Заработало! Вот он этот коварный параметр:
Цитата(Methane @ Jun 4 2013, 16:26) *
pcie.tx_desc[71:64] <= 8'b11111111; --Last BE & 1st BE

До этого я отлаживал плату с длинной данных 1DWORD, соответственно параметр был 8'b00001111; А тестил я с length=2
Поставил как у вас и все заработало. Большое спасибо за консультацию!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.