Jump to content

    

framebuffer драйвер

Пишу драйвер PCF8833 (дисплей от nokia), оказалось взаимодействовать с ядром гораздо сложнее, чем с контроллером LCD.

Дисплей подключен по SPI, в связи с чем такая проблема,

mmap из userspace, похоже нет ни какого хорошего способа узнать, что память была отмэплена и перезаписана, и что новые данные пора отправить контроллеру.

есть два варианта,

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

- обновлять по запросу из userspace, есть там какой то sync но как я понял он совсем не для этого, и ни кто его так не использует

 

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

 

Спасибо,

пока работает только fbcon, pcf8833.c.txt

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Если правильно использовать, то mmap быстрее write (если только в конце всех отрисовок дeлать flush), ну и есть же готовый софт использующий mmap, надо чтобы он работал.

 

vm_area_struct попробую, хотя пока не понятно как.

Share this post


Link to post
Share on other sites

mmap-то быстрее, но ведь все равно SPI в конце, дисплей все равно будет перерисовываться на несколько порядков медленней чем выполняться самый тормознутый write. Здесь в любом случае нужна flush-стратегия - в идеале обновлять нужно только измененные пикселы.

Share this post


Link to post
Share on other sites
Дисплей подключен по SPI, в связи с чем такая проблема,

mmap из userspace, похоже нет ни какого хорошего способа узнать, что память была отмэплена и перезаписана, и что новые данные пора отправить контроллеру.

есть два варианта,

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

- обновлять по запросу из userspace, есть там какой то sync но как я понял он совсем не для этого, и ни кто его так не использует

 

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

 

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

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

Edited by sasamy

Share this post


Link to post
Share on other sites

Кстати насчет подобных конструкций:

 

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 не является обязательной, иначе ядро увидев непустой указатель будет их вызывать - это скажется на производительность ессно в худшую сторону.

Edited by sasamy

Share this post


Link to post
Share on other sites

Этот вариант я уже видел, мне он не понравился по двум причинам,

 

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

 

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

 

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

 

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

 

Да и по поводу atmel spi, сегодня изменяя частоту ядра/памяти обнаружил, что spi_write навсегда блокируется при низких частотах, странно? причину пока не нашел.

Edited by amaora

Share this post


Link to post
Share on other sites

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

 

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

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

К тому же ещё и отсутсвие синхронизации записи кадра в буфер с его отправкой в контрорллер LCD.

Это вас как-то напрягает если fps превышает 25 ? :) вы это никогда не заметите, потому что человеческий глаз не восприимчив к таким быстрым изменениям, так что эти артефакты никогда не видны.

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

я же просто пошутил насчет лучшего варианта - на pcf8833 просто не получится сделать так как на lph88 из-за его девятого бита команда-данные, для него в любом случае придется делать преобразование и дополнительно нагружать процессор.

Да и по поводу atmel spi, сегодня изменяя частоту ядра/памяти обнаружил, что spi_write навсегда блокируется при низких частотах, странно? причину пока не нашел.

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

Share this post


Link to post
Share on other sites

Я понял, только написал не очень ясно. Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти. Это плохое решение не зависимо от того какой контроллер LCD используется.

 

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

Share this post


Link to post
Share on other sites
Я понял, только написал не очень ясно. Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти.

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

Это плохое решение не зависимо от того какой контроллер LCD используется.

Можете предложить лучше чтобы работал mmap в userspace ? нет ? тогда о чем вообще разговор.

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

Вот как - не баг :) и каким таким образом в spi_write вы сможете назначить буфер для приема ?

Edited by sasamy

Share this post


Link to post
Share on other sites
Прямая отправка буфера кадра без перпавковки не отменяет занятости SPI и нагрузки на контроллер памяти. Это плохое решение не зависимо от того какой контроллер LCD используется.

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

Share this post


Link to post
Share on other sites

Ну вот давайте ещё померяемся :)

 

Попробовал сегодня запустить рендер 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

Share this post


Link to post
Share on other sites
Ну вот давайте ещё померяемся :)

 

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

 

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

 

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

 

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

 

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

Edited by sasamy

Share this post


Link to post
Share on other sites

Да в чем разница то? ну растеризатор там вместо mpeg декодера, как это на работу драйвера влияет?

 

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

 

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

 

И ещё раз про atmel_spi,

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

 

Это не баг по тому что автор драйвера видимо писал его зная об этой особенности, это именно особенность.

Edited by amaora

Share this post


Link to post
Share on other sites
Переписать софт было бы правильнее

.....

Это не баг по тому что автор драйвера видимо писал его зная об этой особенности, это именно особенность.

 

В общем не вижу смысла в дальнейшей дискуссии :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this