Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DMA. Потери данных внутри пакета
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Nedd
Здравствуйте, прочитал на хабре статью про DMA контроллер, было решено повторить.
До момента написания драйвера все работает должным образом. Драйвер скомпилировать не удалось, поэтому было принято решение переписать утилиту phys_addr для автономной работы (инициализация интерфейсов, выделение памяти, запись стартового адреса в регистры, запуск транзакции). И здесь возникла проблема:

Были обнаружены потери данных внутри одной транзакции (данные передаются, но теряются некоторые посылки, зависимости установить не удалось).
Причем, потери возникают в том месте, где устанавливается стартовый бит (младший бит в регистре 0хс0000000) в единицу внутри программы. Если же программу поставить на паузу и вручную установить младший бит в регистре 0хс0000000 в единицу, потерь нет (так как описано в статье, утилиты mem и phys_addr).

Программный код обоих вариантов инициализации идентичен. Signal Tap потерь не видит, данные передаются соотетствующим образом.
Такое чувство, что я не замечаю какой-то нюанс, может кто-нибудь подсказать, в чем дело?


P.S. Cyclone V, de1-soc. Был бы рад руководству (документации), по написанию программ для sgdma ядра.
Слева изображение с потеряными посылками (№1,8,9), справа без потерь. Во вложении программный код.
iosifk
Цитата(Nedd @ Aug 10 2015, 14:31) *
Здравствуйте, прочитал на хабре статью про DMA контроллер, было решено повторить.


Так там же написано: "НТЦ Метротек". Позвонить туда и спросить...
johan
Цитата(iosifk @ Aug 10 2015, 14:52) *
Так там же написано: "НТЦ Метротек". Позвонить туда и спросить...

Мне кажется неправильным, если все у кого возникли вопросы по статье, начнут звонить в контору и спрашивать автора.
Представьте себе, что стал известен рабочий номер des00, и все у кого возникли вопросы по констрейнам, вместо создания топиков на форуме, начнут ему звонить на работу?

Правильнее, наверно, автору написать в личку на хабре, либо в комментариях.

В архиве не приложен код на FPGA: вы взяли его из статьи без изменений?
Сообщение о Allignment trap это нормально?

UPD:
Соседний топик смотрели ( http://electronix.ru/forum/index.php?showtopic=129357 )?
Nedd
Да, HDL код используется из статьи (в качестве эталонного), прикрепил во вложении. Привел код к более читаемому виду.

Алгоритм работы с dma следующий:
1.Включить интерфейс HPS-to-FPGA: echo 1 > /sys/class/fpga-bridge/hps2fpga/enable
2.Включить интерфейс fpga2sdram: ./mem.o 0xFFC25080 0x3fff
3.Запустить ./phys_addr, она выделит физический адрес, например 0x2d593000.
4.При использовании интерфейса fpga2sdram нужно адресоваться по словам.Так как слова у нас 128-битные, то адрес слова: 0x2d593000 / 16 = 0x2d59300
5. Запись полученного адреса в регистр ./mem.o 0xC0000002 0x2d59300
6. Запишем длину DMA-транзакции в контрольный регистр номер 3. Длина не должны превышать размера страницы,4096 байт. Так как наш fpga2sdram интерфейс имеет ширину в 128 бит, а размер транзакции указывается в словах, то в третий регистр записывается число 256. ./mem.o 0xC0000006 256.
7. Прочитать данные по адресу 0xC0000000, а потом записать их же, но с установленным нулевым битом. ./mem.o 0xC0000000; прочиталось 0x93000000; ./mem.o 0xC0000000 0x93000001
8. Снять утилиту phys_addr с паузы и прочитать данные.

Проблема возникает на этапе 7, причина пока неизвестна.

P.S. Автору написал, но у него пока нет свободного времени.
iosifk
Цитата(johan @ Aug 10 2015, 22:24) *
Мне кажется неправильным, если все у кого возникли вопросы по статье, начнут звонить в контору и спрашивать автора.
Представьте себе, что стал известен рабочий номер des00, и все у кого возникли вопросы по констрейнам, вместо создания топиков на форуме, начнут ему звонить на работу?

А я считаю это правильным. Для того в статьях и пишут почтовый адрес автора. А уж отвечать или нет, это дело автора. Я всегда отвечаю своим читателям...
Nitrex
Здравствуйте, Nedd. Я столкнулся с похожей проблемой. Вы так и не разобрались с этим вопросом?
Nedd
К сожалению нет, автор так и не ответил, разобраться не получилось, пришлось идти другим путем.
В результате, был использован готовый dma контроллер из qsys, параметры выставляются через контрольные регистры компонента, согласно разделу 27 Embedded Peripherals IP User Guide .
johan
Так получилось, что коллеги топикстартера вышли на меня и попросили глянуть этот кейс на тех платах, на которых я работаю.

Я посмотрел - действительно, воспроизводится - результат аналогичный (видны пропуски).
Для исключения ошибки в FPGA коде я написал свой, который делает аналогичные действия, но пишет шириной данных по 32 бита (вместо 128, как было у автора). Результат тоже аналогичный - видны пропуски, хотя я писал и через интерфейсы fpga2hps и через fpga2sdram.

Если открыть Cyclone V Hard Processor System Technical Reference Manual Figure 1-2: HPS Block Diagram, то видно, что при использовании этих интерфейсов поток данных идет в обход процессора ARM (MPU Subsystem), в том числе его кэша L2 (64 КБ). Следовательно, когда программа в юзерспейсе просит процессор прочитать данные из DDR-памяти, то если данные остались в кэше, то он вычитает из кэша.

Эта идея подтвердилась тем, что в той же самой утилите перед запуском DMA-транзакции сделали фейковую обработку данных вида:
Код
#define BIG_ARR_SIZE 1000000
uint32_t* big_arr;

big_arr = malloc( BIG_ARR_SIZE * sizeof( uint32_t ) );

if( big_arr == NULL ) {
  printf("big_arr: can't alloc\n");
  exit( -1 );
}

int i;

uint32_t sum = 0;
for( i = 0; i < BIG_ARR_SIZE; i++ ) {
  big_arr[i] = rand();
}

for( i = 0; i < BIG_ARR_SIZE; i++ ) {
  sum += big_arr[i];
}


А после DMA-транзакции делали печать sum (для того, чтобы ничего не соптимизировалось).
Идея этой фейковой обработки в том, что данные из кэша которые принадлежали той области памяти, куда будет писать FPGA, сбросятся в DDR.
А когда процессор попросит даные из этой памяти, то он будет обязан взять их из DDR-памяти - т.е. самые новые.

На железе было попробовано - действительно пропуски пропали.

Хак с фейковыми расчетами никуда не годится в реальных задачах: при выделении памяти под DMA вы должны гарантировать, что когда процессор
будет их забирать, он возьмет самые актуальные.

Самый правильный и классический путь - это писать драйвер, который будет заниматься выделением такой памяти (а так же обрабатывать прерывания, если необходимо).

Например, в драйвере aclsoc (Altera OpenCL) для этого делают так:
Код
kalloc_memory = dma_alloc_coherent(NULL, allocated_size, &dma_handle, GFP_KERNEL);
if (kalloc_memory == NULL) {
  return -ENOMEM;
}

// kmalloc returns "kernel logical addresses".
// __pa()          maps "kernel logical addresses" to "physical addresses".
// remap_pfn_range maps "physical addresses" to "user virtual addresses".
// kernel logical addresses are usually just physical addresses with an offset.
// Make the pages uncache-able. Otherwise, will run into consistency issues.
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
      dma_handle >> PAGE_SHIFT,
      size,
      vma->vm_page_prot) < 0) {
  return -EAGAIN;
}


В конце статьи про DMA (http://habrahabr.ru/company/metrotek/blog/248145/) Денис (des333) привел пример драйвера, который делает подобное. Можно воспользоваться им, либо написать какой-то свой.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.