Доступ DMA к пользовательскому пространству Linux (для копирования в память)

Мое встроенное устройство ARM оснащено 16-битным ЖК-дисплеем Linux с кадровым буфером 800x480, который необходимо дважды буферизовать вручную. На данный момент я просто использую memcpy() для записи двойного буфера в фреймбуфер, что ужасно медленно. Цикл while(1){memcpy(lfb,dbuf)} максимально загружает ЦП на 100% и обновляет примерно со скоростью 40 кадров в секунду.

Устройство ARM, которое я использую, и ядро ​​​​Linux поддерживают копирование памяти в память DMA, но мне трудно понять, как я могу получить к этому доступ в программе пользовательского пространства.

Кажется, мне нужно использовать linux/dmaengine.h и dma_async_memcpy_buf_to_buf(), но оказывается, что они доступны только внутри ядра?


person thecoder    schedule 09.09.2015    source источник
comment
Почему бы просто не обновить адрес буфера для обновления экрана? Копирование — это ерунда, и DMA, скорее всего, не будет решением! Просто рассчитайте необходимую скорость передачи — будь то DMA или CPU. Кстати: вы не можете использовать DMA из пользовательского пространства. Если вы думаете на 5сек, вы должны выяснить причину, почему.   -  person too honest for this site    schedule 09.09.2015
comment
Похоже, вы копируете данные из двойного буфера в буфер кадра, а не выполняете двойную буферизацию буфера кадра?   -  person user3528438    schedule 09.09.2015
comment
Олаф, спасибо за ответ, но не надо быть снисходительным. Очевидно, я думал об этом более 5 секунд, иначе я бы не спрашивал здесь. Устройство кадрового буфера не имеет возможности двойной буферизации (использование FBIOPAN_DISPLAY IOCTL невозможно), поэтому я должен выделить его в куче. Разве нет другого пути?   -  person thecoder    schedule 09.09.2015


Ответы (2)


Правильный способ того, что вы делаете, - это вообще не копировать память, а просто использовать встроенную функцию контроллера дисплея для чтения следующего кадра из другого буфера памяти.

Убедитесь, что ваш SoC имеет/не имеет этой функции. Я на 80% уверен, что да.

person sqr163    schedule 09.09.2015
comment
Это Freescale iMX28, который использует драйвер кадрового буфера MXS. Использование FBIOPUT_VSCREENINFO для расширения виртуального буфера кадра до удвоенной высоты ЖК-дисплея возвращает true, но затем повторное чтение FBIOGET_VSCREENINFO показывает, что виртуальная область возвращается к исходной высоте ЖК-дисплея. Использование FBIOPAN_DISPLAY всегда возвращает ошибку. Таким образом, похоже, что драйвер Kernel MXS FB содержит ошибки или неполный. - person thecoder; 09.09.2015

эта информация из: http://pandorawiki.org/Kernel_interface

может быть полезно>

интерфейс фреймбуфера

Доступ к фреймбуферам можно получить через интерфейс Linux fbdev:

fbdev = open("/dev/fb0", O_RDWR); буфер = mmap(0, 800*480*2, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev, 0);

(это базовый пример, без проверки ошибок)

возвращенный указатель можно использовать для рисования на экране.

Обязательно #include для получения доступа к интерфейсу ioctl устройства FB и для доступа к самому ioctl. двойная буферизация

Этого можно добиться с помощью системного вызова FBIOPAN_DISPLAY ioctl. Для этого вам нужно mmap framebuffer двойного размера

буфер1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0); буфер2 = (символ *)память + 800*480*2;

Затем, чтобы отобразить буфер2, вы должны позвонить:

структура fb_var_screeninfo fbvar; ioctl(fbdev, FBIOGET_VSCREENINFO, &fbvar); fbvar.yoffset = 480; ioctl(fbdev, FBIOPAN_DISPLAY, &fbvar);

возврат к буферу 1 будет повторять вышеописанное с fbvar.yoffset = 0. Тройная или счетверенная буферизация может быть реализована с использованием той же техники.

person user3629249    schedule 10.09.2015