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

Kernel module for SG AXI DMA Xilinx

Добрый день! Уважаемые специалисты подскажите пожалуйста, что делаю не так.

Написал свой kernel module для SG AXI DMA (канал S2MM).

Для тестирования задал в дескрипторах два пакета по 32 слова (32 бита на слово).

На мастер SG M AXI отмапировал DDR и BRAM, чтобы по-тестировать модуль при дескрипторах сохраненных в одну или вторую память.

mem.thumb.png.649f67b57b3e33c49e620082c7d99e6e.png

Отображаю BRAM в виртуальное пространство ядра.


	start = desc_physicalAddress; // 0x400000000 -- BRAM address
	len   = 8*1024;
	
	desc_virtualAddress = memremap(desc_physicalAddress, len, MEMREMAP_WB);

	if ( ! desc_virtualAddress ) {
		printk(KERN_ERR "%s: ERROR: desc_virtualAddress remapping FAILED\n", __FUNCTION__);
	}
	printk ( KERN_DEFAULT "%s:%i Descriptors memory phys addr is 0x%x and virt is 0x%x\n", __FUNCTION__, __LINE__, desc_physicalAddress, desc_virtualAddress );
	

Записываю дескрипторы, запускаю DMA.

На шине axi memory для SG наблюдаю как DMA вычитывает все дескрипторы.

sg_br1.thumb.png.92e8744b5f7c1ce70112707bccc4c072.png

sg_br2.thumb.png.1249e92557f8b704956d5b1db77f3bc5.png

SG DMA отрабатывает как и задумано.

Теперь пробую сохранить дескрипторы в DDR. В DT резервирую память.


/ {
   reserved-memory {
      #address-cells = <1>;
      #size-cells = <1>;
      ranges;
  
      reserved: buffer@0x38000000 {
         no-map;
         reg = <0x38000000 0x00080000>;
      };
   };
  
   reserved-driver@0 {
      compatible = "xlnx,reserved-memory";
      memory-region = <&reserved>;
   };
};

После старта ядра проверяю, что память успешно зарезервировалась (под дескрипторы 0x38000000-0x380800000 ).

root@test:~# cat /proc/iomem
00000000-37ffffff : System RAM
	00008000-008fffff : Kernel code
	00a00000-00a517bf : Kernel data
38080000-3fffffff : System RAM

 

Получаю указатель на память в виртуальном пространстве


	start = desc_physicalAddress; // 0x380000000 -- in DDR address
	len   = 512*1024;
	
	desc_virtualAddress = memremap(desc_physicalAddress, len, MEMREMAP_WB);

	if ( ! desc_virtualAddress ) {
		printk(KERN_ERR "%s: ERROR: desc_virtualAddress remapping FAILED\n", __FUNCTION__);
	}
	printk ( KERN_DEFAULT "%s:%i Descriptors memory phys addr is 0x%x and virt is 0x%x\n", __FUNCTION__, __LINE__, desc_physicalAddress, desc_virtualAddress );

Запускаю AXI DMA и получаю ошибку SGIntErr (internal error). Проверяю данные на axi шине SG. действительно, дескрипторы вычитаны неправильно.

sg_ddr.thumb.png.54202359216d8a568e44cf01dce1de65.png

По сравнению с BRAM все одинаково. Не могу понять, что не так. 

 

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


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

23 minutes ago, gosha-z said:

Я же вам давал ссылки как правильно работать с DMA в ядре...

за ссылки спасибо, но я быстрей запустился используя platform_get_resource для работы с регистрами DMA, прерываниями и dma_alloc_coherent для буфера ДМА.

Если выложите простой пример запуска DMA_FROM_DEVICE канала DMA на основе документации по вашей ссылке, буду очень признателен.

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


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

9 minutes ago, gosha-z said:

Георгий, спасибо большое, эта ссылка у меня сохранена. Но я написал свой модуль и он работает. Остался вопрос только с ioremap для памяти в DDR.

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


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

В смысле как делать remap памяти ядра в userspace? Почитайте исходники и DMA-HOW-TO, там все написано. У меня, по крайней мере, сделано ровно так и оно работает...

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


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

remap делаю без проблем. Не понятно вот что. Записываю дескрипторы


			iowrite32 ( desc_physicalAddress + 0x40, desc_virtualAddress + 0x0000);
			iowrite32 ( lp->dma_buffer_physical_address, desc_virtualAddress + 0x0008);
			iowrite32 ( 0x8000080, desc_virtualAddress + 0x0018);
			
			iowrite32 ( desc_physicalAddress + 0x40, desc_virtualAddress + 0x0040);
			iowrite32 ( lp->dma_buffer_physical_address + 0x80, desc_virtualAddress + 0x0048);
			iowrite32 ( 0x4000080, desc_virtualAddress + 0x0058);			
			

Виртуальный адрес получаю с помощью memremap

start = desc_physicalAddress; // 0x380000000 -- in DDR address
len   = 512*1024;
	
desc_virtualAddress = memremap(desc_physicalAddress, len, MEMREMAP_WB);

Так вот, если  desc_physicalAddress подставляю адрес BRAM, то SG DMA работает, а если desc_physicalAddress подставляю адрес зарезервированной в DDR памяти, то SG DMA вычитывает правильно только несколько первых дескрипторов и виснет.

 

Пока вам отвечал, разобрался)) Ошибка на невнимательность - не проинициализировал desc_physicalAddress (когда использую BRAM там все нули сразу), когда DDR - там мусор. Вообщем SG вычитывал правильные дескрипторы и мусор, поэтому и вис.

Проинициализировал зарезервированную область DDR и все заработало

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


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

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

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

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

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

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

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

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

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

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