Порт на Qt за STM32

Порт на Qt за STM32Добър ден! Ние сме в проекта Embox започнахме с Qt на STM32F7-Discovery и искаме да споделим за него. По-рано разказахме как успяхме да стартираме OpenCV.

Qt е кросплатформен фреймворк, който включва не само графични компоненти, но и такива неща като QtNetwork, набор от класове за работа с бази данни, Qt for Automation (включително за реализация на IoT) и много други. Разработчиците от екипа на Qt предварително предвидиха използването на Qt в вградени системи, затова библиотеките са доста добре конфигурируеми. Въпреки това, до наскоро, малко хора се замисляха за портирование на Qt на микроконтролери, вероятно защото задачата изглежда сложна — Qt е голям, MCU са малки.

От друга страна, в момента съществуват микроконтролери, предназначени за работа с мултимедия и надхвърлящи първите Pentium процесори. Около година назад в блога на Qt се появи пост. Разработчиците направиха порт на Qt под ОС RTEMS и стартираха примери с виджети на няколко платформи под управление на stm32f7. Това ни заинтересува. Забеляза се, и самите разработчици пишат за това, че Qt забавя на STM32F7-Discovery. Нас ни заинтригува, можем ли да стартираме Qt под Embox, като не просто нарисуваме виджет, а стартираме анимация.

В Embox отдавна е портировано Qt 4.8, затова решихме да опитаме с него. Избрахме приложението moveblocks — пример за пружиниста анимация.

Qt moveblocks на QEMUПорт на Qt за STM32

Първо конфигурираме Qt с минимален набор от компоненти, необходими за поддръжка на анимацията. За това съществува опция “-qconfig minimal,small,medium …”. Тя свързва конфигурационен файл от състава на Qt с множество макроси — какво да включим/какво да изключим. След тази опция добавяме в конфигурацията други флагове, ако искаме да изключим нещо допълнително. Ето пример на нашата конфигурация.

За да заработи Qt, трябва да добавим слой на съвместимост с ОС. Един от начините е да се реализира QPA (Qt Platform Abstraction). За основа взехме готовия плагин fb_base от състава на Qt, на базата на който работи QPA за Linux. В резултат се получи малък плагин emboxfb, който предоставя на Qt framebuffer на Embox, а след това рисува без допълнителна помощ.

Ето как изглежда създаването на плъгин

QEmboxFbIntegration::QEmboxFbIntegration()
    : fontDb(new QGenericUnixFontDatabase())
{
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    const char *fbPath = "/dev/fb0";

    fbFd = open(fbPath, O_RDWR);
    if (fbFd setPhysicalSize(QSize(fbWidth, fbHeight));
    mScreens.append(mPrimaryScreen);

    this->printFbInfo();
}

Така ще изглежда прерисуването

QRegion QEmboxFbScreen::doRedraw()
{
    QVector rects;
    QRegion touched = QFbScreen::doRedraw();

    DPRINTF("QEmboxFbScreen::doRedrawn");

    if (!compositePainter) {
        compositePainter = new QPainter(mFbScreenImage);
    }

    rects = touched.rects();
    for (int i = 0; i drawImage(rects[i], *mScreenImage, rects[i]);
    }
    return touched;
}

В крайна сметка, с включена оптимизация на компилатора по размер на паметта -Os, образът на библиотеката стана 3.5 Мб, което, разбира се, не се побира в основната памет на STM32F746. Както вече споменахме в друга наша статия за OpenCV, на тази платка има:

  • 1 Мб ROM
  • 320 Кб RAM
  • 8 Мб SDRAM
  • 16 Мб QSPI

Тъй като за OpenCV вече беше добавена поддръжка за изпълнение на код от QSPI, решихме да започнем като заредим образа на Embox с Qt изцяло в QSPI. И ура, всичко почти веднага се стартира от QSPI! Но, както и при OpenCV, се оказа, че работи прекалено бавно.

Порт на Qt за STM32

Следователно решихме да направим така — първо копираме образа в QSPI, след това го зареждаме в SDRAM и изпълняваме оттам. От SDRAM стана малко по-бързо, но все пак далеч от QEMU.

Порт на Qt за STM32

След това имаше идея да включим плаваща запетая — защото Qt прави някои изчисления на координатите на квадратите в анимацията. Опитахме, но не получихме видимо ускорение, въпреки че статии разработчиците на Qt твърдяха, че FPU дава значителен прираст в скоростта за "dragging animation" на тъчскрийн. Може би в moveblocks изчисленията с плаваща запетая са много по-малко и това зависи от конкретния пример.

Най-ефективната идея се оказа прехвърлянето на фреймбуфера от SDRAM в вътрешната памет. За целта направихме размерите на екрана не 480×272, а 272×272. Освен това намалихме дълбочината на цвета от A8R8G8B8 на R5G6B5, като по този начин намалихме размера на един пиксел от 4 на 2 байта. Получихме размер на фреймбуфера 272 * 272 * 2 = 147968 байта. Това доведе до значително увеличаване на скоростта, вероятно най-забележимо, анимацията стана почти плавна.

Последната оптимизация се състоеше в изпълнението на кода на Embox от RAM, а на Qt от SDRAM. За целта първо свързахме статично Embox заедно с Qt, но сегментите text, rodata, data и bss на библиотеката поставихме в QSPI, за да можем след това да копираме в SDRAM.

section (qt_text, SDRAM, QSPI)
phdr	(qt_text, PT_LOAD, FLAGS(5))

section (qt_rodata, SDRAM, QSPI)
phdr	(qt_rodata, PT_LOAD, FLAGS(5))

section (qt_data, SDRAM, QSPI)
phdr	(qt_data, PT_LOAD, FLAGS(6))

section (qt_bss, SDRAM, QSPI)
phdr	(qt_bss, PT_LOAD, FLAGS(6))

Чрез изпълнението на кода на Embox от ROM също получихме забележимо увеличаване на скоростта. В резултат анимацията стана доста плавна:

Възпроизведи видео

В края, подготвяйки статията и опитвайки различни конфигурации на Embox, се установи, че Qt moveblocks работи чудесно и от QSPI с фреймбуфер в SDRAM, а тясното място всъщност беше размерът на фреймбуфера! Очевидно, за да се преодолее началното "слайдшо" е било достатъчно ускорение от 2 пъти просто чрез намаляване на размера на фреймбуфера. А да се постигне такъв резултат чрез прехвърляне само на кода на Embox в различни бързи памети не се оказа удачно (ускорението беше не 2, а около 1.5 пъти).

Как да опитате сами

Ако имате STM32F7-Discovery, можете сами да стартирате Qt под Embox. Можете да прочетете как става това на нашия вики.

Заключение

В крайна сметка успяхме да стартираме Qt! Трудността на задачата, според нас, е малко преувеличена. Разбира се, трябва да се вземат предвид спецификите на микроконтролерите и наистина да се разбере архитектурата на изчислителните системи. Резултатите от оптимизацията показват известния факт, че най-тясното място в изчислителната система не е процесорът, а паметта.

Тази година ще участваме на фестивала TechTrain. Там ще разкажем по-подробно и ще покажем Qt, OpenCV на микроконтролери и други наши постижения.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster