Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: framebuffer драйвер
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
amaora
Пишу драйвер PCF8833 (дисплей от nokia), оказалось взаимодействовать с ядром гораздо сложнее, чем с контроллером LCD.
Дисплей подключен по SPI, в связи с чем такая проблема,
mmap из userspace, похоже нет ни какого хорошего способа узнать, что память была отмэплена и перезаписана, и что новые данные пора отправить контроллеру.
есть два варианта,
- регулярно проверять буфер на изменения, не подходит т.к. это постоянный расход времени процессора
- обновлять по запросу из userspace, есть там какой то sync но как я понял он совсем не для этого, и ни кто его так не использует

может кто нибудь знает вариант получше?

Спасибо,
пока работает только fbcon, Нажмите для просмотра прикрепленного файла
Harbour
Смысл использовать mmap при последовательном обмене в конце ? В данном случае юзают стандартый open/write. Насчет callback'ов - кажись в vm_area_struct есть указатели на f()-ии типа swapout/nopage/sync - вот последняя при каждой записи и вызывается.
amaora
Если правильно использовать, то mmap быстрее write (если только в конце всех отрисовок дeлать flush), ну и есть же готовый софт использующий mmap, надо чтобы он работал.

vm_area_struct попробую, хотя пока не понятно как.
Harbour
mmap-то быстрее, но ведь все равно SPI в конце, дисплей все равно будет перерисовываться на несколько порядков медленней чем выполняться самый тормознутый write. Здесь в любом случае нужна flush-стратегия - в идеале обновлять нужно только измененные пикселы.
sasamy
Цитата(amaora @ Jun 12 2009, 00:46) *
Дисплей подключен по SPI, в связи с чем такая проблема,
mmap из userspace, похоже нет ни какого хорошего способа узнать, что память была отмэплена и перезаписана, и что новые данные пора отправить контроллеру.
есть два варианта,
- регулярно проверять буфер на изменения, не подходит т.к. это постоянный расход времени процессора
- обновлять по запросу из userspace, есть там какой то sync но как я понял он совсем не для этого, и ни кто его так не использует

может кто нибудь знает вариант получше?


sync - точно не помню, но это не подойдет, помоему эта ф-ция вызывается перед тем как fbcon что-то хочет с буфером сделать - типа буть готов, в любом случае fbcon не и меет никакого отношения к тому что делает юзер из своего юзерспейса smile.gif для него это такой же кусок памяти как для юзера.
Вот тут http://www.at91.com/samphpbb/viewtopic.php...b1577028328bab0 мой вариант получше smile.gif и экран побольше и видео в mpeg4 летает smile.gif Правда пришлось отказаться от тормозного драйвера spi в исполнении atmel - они слишком расточительны и самое главное в них не реализовано переключение bits_per_word для spi_transfer. Смысл простой - постоянная синхронизация видеобуфера и lcd. Буфер одновременно смапен на dma и доступен процессору, поэтому при наличии dma на контроллере spi процессор не несет никакой дополнительной нагрузки - только от того что хочет юзер запихнуть в видеобуфер и что пишет туда fbcon. В lph88 можно сказать контроллеру - "а сейчас у нас летят данные" и пока не дернешь cs он будет воспринимать их как данные, может я что-то упустил на pcf8833 но там мне так не удалось сделать, чтобы передавать весь буфер в том виде как он есть - приходилось делать цикл который запихивал данные в другой буфер а его уже перекидывал по spi dma контроллер в lcd.
sasamy
Кстати насчет подобных конструкций:

Код
static int
pcf8833_sync(struct fb_info *info)
{
    //struct pcf8833_par *par = info->par;

    return 0;
}

.....

static struct fb_ops pcf8833_ops = {
    .owner          = THIS_MODULE,
    .fb_read        = fb_sys_read,
    .fb_write       = fb_sys_write,
    .fb_fillrect    = pcf8833_fillrect,
    .fb_copyarea    = pcf8833_copyarea,
    .fb_imageblit   = pcf8833_imageblit,
    .fb_blank       = pcf8833_blank,
    .fb_setcolreg    = pcf8833_setcolreg,
    .fb_sync    = pcf8833_sync
};

Не нужно вписывать функции-пустышки там где они необязательны, а fb_sync не является обязательной, иначе ядро увидев непустой указатель будет их вызывать - это скажется на производительность ессно в худшую сторону.
amaora
Этот вариант я уже видел, мне он не понравился по двум причинам,

1. Прямая работа с контроллером SPI, это ограничевает примерение драйвера и делает код более запутанным. Про преключение bits_per_word между несколькими transfer не понял, почему это так важно? для PCF8833 этого не надо, здесь размер слова фиксорован, 9 бит (если тоже не упустил чего то, читая datasheet). Правильнее было бы добавить то чего не хватает в atmel_spi.c а не отказываться от всей spi подситемы ядра. Да и не мало кода похоже от туда и было взято smile.gif

2. Постоянная отправка данных, это означает, что SPI всегда занят, что регулярно производится "перепаковка" фреймбуфера в формат подходящий для отправки, что DMA всегда отбирает часть ресурса доступа к памяти у ядра. К тому же ещё и отсутсвие синхронизации записи кадра в буфер с его отправкой в контрорллер LCD.

А то, что для PCF8833 приходися выравнивать 9-битные данные по 16 битам, не относится к проблеме взаимодействия драйвера с ядром и процессами пользователя. Не стоит все смешивать, это позволит более просто менять что либо.

Видимо лучший вариант это все таки read/write, хотя можно записывать данные через mmap, а потом делать write с длиной 1, и это будет вызывать flush всего буфера. Пока так и сделал, отказался от отправки только измененных данных. fbcon похоже делает отрисовки посимвольно, и это заставляло ядро много времени проводить в прерываниях, судя по тому, что показывает top. В большинстве случаев будет обновлятся всё, да и в fbcon очень скоро начинается сколлинг. По этому так похоже даже лучше.

Да и по поводу atmel spi, сегодня изменяя частоту ядра/памяти обнаружил, что spi_write навсегда блокируется при низких частотах, странно? причину пока не нашел.
sasamy
По поводу переключения bits_per_word - не совпадает endian процессора и lcd, если передавать буфер в неизменном виде в 8 -битном режиме то все цвета перепутаются, поэтому при передаче содержимого видеобуфера я переключаюсь в 16 битный режим - pdc копирует целиком полуслово в соответствии с endian процессора а spi передает его как и нужно для lcd msb-first. Почему все не передаю в 16 битном режиме - потому что там мешается всего один байт в протоколе котрый нарушает выравнивание на полуслове, если впихнуть ноль для выравнивания то lcd вообще обламывается и ничего не работает.

Цитата
Постоянная отправка данных, это означает, что SPI всегда занят, что регулярно производится "перепаковка" фреймбуфера в формат подходящий для отправки,

вы не поняли сути этого драйвера - он коренным образом отличается от того что я делал на pcf8833 - не происходит никакй перепаковки видеобуфера - он отправляется в неизменном виде, именно в этом вся прелесть, процессор не занят теперь лишней перепаковкой.
Цитата
К тому же ещё и отсутсвие синхронизации записи кадра в буфер с его отправкой в контрорллер LCD.

Это вас как-то напрягает если fps превышает 25 ? smile.gif вы это никогда не заметите, потому что человеческий глаз не восприимчив к таким быстрым изменениям, так что эти артефакты никогда не видны.
Цитата
А то, что для PCF8833 приходися выравнивать 9-битные данные по 16 битам, не относится к проблеме взаимодействия драйвера с ядром и процессами пользователя.

я же просто пошутил насчет лучшего варианта - на pcf8833 просто не получится сделать так как на lph88 из-за его девятого бита команда-данные, для него в любом случае придется делать преобразование и дополнительно нагружать процессор.
Цитата
Да и по поводу atmel spi, сегодня изменяя частоту ядра/памяти обнаружил, что spi_write навсегда блокируется при низких частотах, странно? причину пока не нашел.

В атмеловских драйверах spi очень много багов. Я не стал писать багрепорты, потому что похоже никому не нужно это и все смирились с их глючностью smile.gif Для примера - попробуйте передать длинное сообщение (превышающее страницу памяти 4 кб) по spi_write - увидите много странного smile.gif Могу рассказать где баг, но пока не знаю как поправить. Кстати я дописывал у себя поддержку bits_per_word для spi_transfer, но потом все равно решил отказаться от драйвера атмел.
amaora
Я понял, только написал не очень ясно. Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти. Это плохое решение не зависимо от того какой контроллер LCD используется.

По поводу SPI сообщения длиной больше страницы, так надо явно указать и rx и tx буфер, тогда нормально отправится, это не баг.
sasamy
Цитата(amaora @ Jun 15 2009, 19:48) *
Я понял, только написал не очень ясно. Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти.

Занят только один интерфейс - со вторым можете делать что угодно, в любом случае я предпочту использовать устройство а не хранить его для какаих-то высших целей, к тому же контроллер памяти видмо и неподозревает что сильно занят smile.gif с этим драйвером нормально смотрятся фмльмы в mpeg4.
Цитата
Это плохое решение не зависимо от того какой контроллер LCD используется.

Можете предложить лучше чтобы работал mmap в userspace ? нет ? тогда о чем вообще разговор.
Цитата
По поводу SPI сообщения длиной больше страницы, так надо явно указать и rx и tx буфер, тогда нормально отправится, это не баг.

Вот как - не баг smile.gif и каким таким образом в spi_write вы сможете назначить буфер для приема ?
sasamy
Цитата(amaora @ Jun 15 2009, 19:48) *
Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти. Это плохое решение не зависимо от того какой контроллер LCD используется.

Кстати - если вы считаете использовать dma по прямому назначению плохой идеей - посмотрите top во время банального скролинга хотя бы одного экрана с тем вариантом котрый вы приняли за хорошую идею - он нагрузит процессор по самые помидоры, у меня процессор занят не более 50% при воспроизведении видео в mpeg4 с звуковой дорожкой в mp3. Даже если вы каким-то грязным хаком сможете отлавливать изменеия смапеной памяти даю 100% гарантию что видео вам там никогда не увидеть даже с несжатого потока - только слайдшоу.
amaora
Ну вот давайте ещё померяемся smile.gif

Попробовал сегодня запустить рендер 3д кубика, портировано очень коряво, сначала рендерится в 8бит цвет, потом преобразуется в 16бит, и делается write (mmap не используется). Результат при 40 fps,
CPU: 27.8% usr 3.8% sys 0.0% nic 63.4% idle 0.0% io 3.8% irq 0.9% sirq

Отрисовка 2K полигональной модели ~6 fps,
CPU: 97.0% usr 2.9% sys 0.0% nic 0.0% idle 0.0% io 0.0% irq 0.0% sirq

Скроллинг, top -d1 | tee /dev/tty0
CPU: 0.9% usr 7.7% sys 0.0% nic 89.3% idle 0.0% io 0.0% irq 1.9% sirq

И самое главное, top -d1
CPU: 0.9% usr 0.0% sys 0.0% nic 99.0% idle 0.0% io 0.0% irq 0.0% sirq

ни какой лишней нагрузки, когда ни чего не рисуется.

Мой вариант это отказ от mmap, или использование mmap совместно с flush (write(fd, ..., 1)). Да надо будет править софт использующий mmap.

http://paravozeg.narod.ru/pcf8833.c.gz
sasamy
Цитата(amaora @ Jun 16 2009, 14:05) *
Ну вот давайте ещё померяемся smile.gif


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

Цитата
ни какой лишней нагрузки, когда ни чего не рисуется.


дааа - весомый аргумент smile.gif а вы только представьте когда питание от него отключить - вообще красота.

Цитата
Мой вариант это отказ от mmap, или использование mmap совместно с flush (write(fd, ..., 1)). Да надо будет править софт использующий mmap.


Вы то можете отказываться от mmap только вот все остальные используют его весьма часто - практически всегда smile.gif напрямую работать будет только fbcon - всё. Такой драйвер для графического lcd нужен как как как для русалки лыжи - не проще тогда писать драйверы под конкретные задачи а не притягивать за уши framebuffer ? переписывать софт под конкретный драйвер - это конечно достойная задача - главное драйвер есть, но тогда причем тут вообще linux ? smile.gif
amaora
Да в чем разница то? ну растеризатор там вместо mpeg декодера, как это на работу драйвера влияет?

Переписать софт было бы правильнее, не плохо бы ещё сделать нормальную синхронизацию (ну то есть flush должен блокировать процесс или сообщать, что тот слишком часто шлет новые данные) а не пропуск кадров. Только это все не оправдано для такого дисплея, там 20 кадров в секунду похоже предел самого LCD.

Но скорее сделаю как проще, добавлю свой ioctl, для включения/отключения постоянной отправки кадров в контроллер LCD, а из userspace, когда надо запустить "не правленный" софт, можно включать это. Думаю это окончательный и лучший вариант.

И ещё раз про atmel_spi,
spi_write это синхронная функция, то есть явно не для больших объемов данных. Да можно было бы усложнить драйвер и избавится от этого недостатка, это ворос равновесия между сложностью интерфейса и реализации. Вы похоже сторонник хорошего внешнего интерфейса, и пусть будет кривая (но работающая) его реализация, так?

Это не баг по тому что автор драйвера видимо писал его зная об этой особенности, это именно особенность.
sasamy
Цитата(amaora @ Jun 16 2009, 17:00) *
Переписать софт было бы правильнее
.....
Это не баг по тому что автор драйвера видимо писал его зная об этой особенности, это именно особенность.


В общем не вижу смысла в дальнейшей дискуссии smile.gif
VDV
подскажите пожалуйста, можно где-то прочитать о том, что такое фрейм буфер?
в чем его отличие от символьного устройства?
(sceleton.c видел)
как с ним работать со стороны пользовательского пространства?
нашел только документы от 2000 и 2002 года.
технология с тех пор не менялась?
sasamy
Цитата(VDV @ May 24 2010, 14:19) *
подскажите пожалуйста, можно где-то прочитать о том, что такое фрейм буфер?


Это буфер окна smile.gif

Цитата
в чем его отличие от символьного устройства?


В терминах системы это и есть символьное устройство.

Цитата
(sceleton.c видел)
как с ним работать со стороны пользовательского пространства?


Как с символьным устройством - read/write или mmap (последний чаще всего, вернее первый я кроме консоли нигде не встречал)

Цитата
нашел только документы от 2000 и 2002 года.
технология с тех пор не менялась?


Да какие там технлогии - это просто кусок памяти который имеет структуру в соответствии с текущим режимом: разрешение и цветность. Для fbcon кроме того есть специальные ф-ции с помощью которых можно ускорить работу с кусором или скролингом экрана - если это не поддерживается устройством аппаратно то их нет смысла эмулировать програмно, они не нужны для нормальной работы. Для примера простой вариант: экран 320х200@16 будет соответствовать сишному массиву uin16t fbscreen[200][320]; и для 16 бит пиксель состоит из rgb 565.
VDV
тогда напрашиваются 2 вопроса.
1. если это просто разделяемый между user и kernel space буфер памяти,
как происходит уведомление драйвера о необходимости перерисовки?
как происходит оптимизация перерисовки?
или же все тупо:
user space заполняет память, а драйвер просто с заданной частотой обновления перекидывает его на экран?

2. программы пользовательского пространства как-то видимо должна получать параметры дисплея (через ioctl?) и понимать, отрисовку чего видеокарта может ускорить, а что надо эмулировать программно.
как это делается?
если через ioctl, значит, есть стандартные коды запросов?
sasamy
Цитата(VDV @ May 25 2010, 12:18) *
тогда напрашиваются 2 вопроса.
1. если это просто разделяемый между user и kernel space буфер памяти,
как происходит уведомление драйвера о необходимости перерисовки?
как происходит оптимизация перерисовки?
или же все тупо:
user space заполняет память, а драйвер просто с заданной частотой обновления перекидывает его на экран?

2. программы пользовательского пространства как-то видимо должна получать параметры дисплея (через ioctl?) и понимать, отрисовку чего видеокарта может ускорить, а что надо эмулировать программно.
как это делается?
если через ioctl, значит, есть стандартные коды запросов?


1 Если mmap то никак, read/write - я думаю с этим понятно - пишешь свои ф-ции и обрабатываешь переданные из/в юзерспейс данные. Вообще это сегодня появились всякие SoC, lcd и framebuffer используют как некий слой абстракции над железом, изначально он использовался в x86 по назначению - это был прямой доступ к памяти видеоконтроллера. Если видеобуфер выделяется в озу то да, так и делают - постоянно обновляется экран.
2 Я думаю в Интернете немало информации чтобы спрашивать все подряд на форуме smile.gif
VDV
Цитата(sasamy @ May 25 2010, 14:00) *
2 Я думаю в Интернете немало информации чтобы спрашивать все подряд на форуме smile.gif

я потому и спрашиваю на форуме, что не смог найти в интернете.
либо я просто не смог правильно задать вопрос гуглу, чтобы он смог ответить.
а чтобы правильно ему задать вопрос, надо понять, что спрашивать.
sasamy
Цитата(VDV @ May 25 2010, 13:03) *
я потому и спрашиваю на форуме, что не смог найти в интернете.



Да перестаньте - это смешно. Я например обычно начинаю поиск в документации идущей в исходниках ядра, как ни страноо там есть вот это:
Код
# pwd
/usr/src/linux-2.6.33/Documentation/fb


Совсем странно что там есть описание fbcon и собственно fb
fbcon.txt
framebuffer.txt

Например framebuffer.txt нам говорит:
Цитата
/dev/fb* also allows several ioctls on it, by which lots of information about
the hardware can be queried and set. The color map handling works via ioctls,
too. Look into <linux/fb.h> for more information on what ioctls exist and on
which data structures they work. Here's just a brief overview:



Теперь достаточно посмотреть include/linux/fb.h
Код
# cat fb.h | grep FBIO
#define FBIOGET_VSCREENINFO    0x4600
#define FBIOPUT_VSCREENINFO    0x4601
#define FBIOGET_FSCREENINFO    0x4602
#define FBIOGETCMAP        0x4604
#define FBIOPUTCMAP        0x4605
#define FBIOPAN_DISPLAY        0x4606
#define FBIO_CURSOR            _IOWR('F', 0x08, struct fb_cursor_user)
#define FBIO_CURSOR            _IOWR('F', 0x08, struct fb_cursor)
/* #define FBIOGET_MONITORSPEC    0x460C */
/* #define FBIOPUT_MONITORSPEC    0x460D */
/* #define FBIOSWITCH_MONIBIT    0x460E */
#define FBIOGET_CON2FBMAP    0x460F
#define FBIOPUT_CON2FBMAP    0x4610
#define FBIOBLANK        0x4611        /* arg: 0 or vesa level + 1 */
#define FBIOGET_VBLANK        _IOR('F', 0x12, struct fb_vblank)
#define FBIO_ALLOC              0x4613
#define FBIO_FREE               0x4614
#define FBIOGET_GLYPH           0x4615
#define FBIOGET_HWCINFO         0x4616
#define FBIOPUT_MODEINFO        0x4617
#define FBIOGET_DISPINFO        0x4618
VDV
видимо я опять задал не тот вопрос...
даже не знаю как сформулировать...
вот смотрите.
есть драйвер с кадровым буфером.
это символьное устройство.
следовательно, подразумевается, что работа с ним - это операции чтения и записи.
однако, это видео-устройство. следовательно должны быть какие-то спец вызовы.
ну и видимо, они как-то должны зависеть от способностей карты к ускорению.
если посмотреть на скелет драйвера, видно, что там есть место для функций акселерации.
но если есть эти функции, значит, если в драйвере они не реализованы, их кто-то должен делать за него.
так?
то есть видимо
драйвер - графическая подсистема - программа.
и следовательно, должны быть, наверно, стандартные вызовы?
или же в линуксе нет такой подсистемы? (я не про X сервер!!!)
как тогда обращаться к этим функциям акселерации драйвера?
и напрашивается вопрос:
а если есть новое устройство, которое умеет ускорять нечто новое (отрисовку шариков, например), для чего не предусмотрены функции в скелете, как они задействуются?

видимо, не я один че-то не понимаю...
http://linuxhaters.blogspot.com/2008/06/ni...pen-source.html
VDV
нашел наконец-то что-то
http://books.google.ru/books?id=sTDHUr4eGY...p;q&f=false
VDV
вопрос появился
написал драйвер для своего дисплея.
оформил как внешний модуль
определил для вызовов в нем функции sys_fillrect и подобные ей от системы.
при компиляции получаю предупреждения, что таких функций в ядре нет.
не могу в меню найти этий опций!
попробовал прямо в .config включить, но это не срабатывает.
как включить их компиляцию?

далее сделал пока так:
отключил их из списка в fops и в ядре выключил консоль для кадрового буфера.
драйвер теперь грузится.
для проверки делаю так:
# cat test > /dev/fb0
cat: write error: File too large

файл test имеет размер 1 байт.
куда копать?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.