Jump to content

    
Aleksei_Rostov

Kernel module for SG AXI DMA Xilinx

Recommended Posts

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

Написал свой 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 все одинаково. Не могу понять, что не так. 

 

Share this post


Link to post
Share on other sites
23 minutes ago, gosha-z said:

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

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

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

Share this post


Link to post
Share on other sites
9 minutes ago, gosha-z said:

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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 и все заработало

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.