Пренос Кт-а на СТМ32

Пренос Кт-а на СТМ32Добар дан Ми смо у пројекту Ембок покренуо Кт на СТМ32Ф7-Дисцовери и желео бих да причамо о томе. Раније смо већ рекли како смо успели да лансирамо ОпенЦВ.

Кт је вишеплатформски оквир који укључује не само графичке компоненте, већ и ствари као што су КтНетворк, скуп класа за рад са базама података, Кт за аутоматизацију (укључујући имплементацију ИоТ-а) и још много тога. Кт тим је био проактиван у коришћењу Кт-а у уграђеним системима, тако да су библиотеке прилично конфигурабилне. Међутим, донедавно је мало људи размишљало о портовању Кт-а на микроконтролере, вероватно зато што се такав задатак чини тешким – Кт је велики, МЦУ-ови мали.

С друге стране, тренутно постоје микроконтролери дизајнирани за рад са мултимедијом и супериорнији од првих Пентиума. Пре отприлике годину дана појавио се Кт блог брзо. Програмери су направили порт за Кт за РТЕМС ОС и покренули примере са виџетима на неколико плоча које користе стм32ф7. Ово нас је заинтересовало. Било је приметно, а и сами програмери пишу о томе, да је Кт спор на СТМ32Ф7-Дисцовери. Питали смо се да ли можемо да покренемо Кт под Ембок-ом, а не само да нацртамо виџет, већ да покренемо анимацију.

Кт 4.8 је већ дуже време портован у Ембок, па смо одлучили да га испробамо на њему. Одабрали смо апликацију мовеблоцкс - пример еластичне анимације.

Кт покретни блокови на КЕМУПренос Кт-а на СТМ32

За почетак, конфигуришемо Кт, ако је могуће, са минималним скупом компоненти потребних за подршку анимације. За ово постоји опција „-кцонфиг минимално,мало,средње...“. Повезује конфигурациону датотеку из Кт-а са многим макроима - шта да омогући / шта да онемогући. Након ове опције, додамо друге заставице у конфигурацију ако желимо да онемогућимо нешто друго. Ево примера нашег конфигурација.

Да би Кт функционисао, потребно је да додате слој компатибилности са оперативним системом. Један од начина је имплементација КПА (Кт Платформ Абстрацтион). За основу смо узели готов фб_басе додатак укључен у Кт, на основу којег ради КПА за Линук. Резултат је мали додатак који се зове ембокфб, који Кт-у обезбеђује Ембок-ов фрамебуффер, а затим га црта без икакве помоћи споља.

Овако изгледа креирање додатка

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 (fbPath < 0) {
        qFatal("QEmboxFbIntegration: Error open framebuffer %s", fbPath);
    }
    if (ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        qFatal("QEmboxFbIntegration: Error ioctl framebuffer %s", fbPath);
    }
    if (ioctl(fbFd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        qFatal("QEmboxFbIntegration: Error ioctl framebuffer %s", fbPath);
    }
    fbWidth        = vinfo.xres;
    fbHeight       = vinfo.yres;
    fbBytesPerLine = finfo.line_length;
    fbSize         = fbBytesPerLine * fbHeight;
    fbFormat       = vinfo.fmt;
    fbData = (uint8_t *)mmap(0, fbSize, PROT_READ | PROT_WRITE,
                             MAP_SHARED, fbFd, 0);
    if (fbData == MAP_FAILED) {
        qFatal("QEmboxFbIntegration: Error mmap framebuffer %s", fbPath);
    }
    if (!fbData || !fbSize) {
        qFatal("QEmboxFbIntegration: Wrong framebuffer: base = %p,"
               "size=%d", fbData, fbSize);
    }

    mPrimaryScreen = new QEmboxFbScreen(fbData, fbWidth,
                                        fbHeight, fbBytesPerLine,
                                        emboxFbFormatToQImageFormat(fbFormat));

    mPrimaryScreen->setPhysicalSize(QSize(fbWidth, fbHeight));
    mScreens.append(mPrimaryScreen);

    this->printFbInfo();
}

А овако ће изгледати прецртавање

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

    DPRINTF("QEmboxFbScreen::doRedrawn");

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

    rects = touched.rects();
    for (int i = 0; i < rects.size(); i++) {
        compositePainter->drawImage(rects[i], *mScreenImage, rects[i]);
    }
    return touched;
}

Као резултат тога, са омогућеном оптимизацијом компајлера за величину меморије -Ос, слика библиотеке је била 3.5 МБ, што се наравно не уклапа у главну меморију СТМ32Ф746. Као што смо већ писали у нашем другом чланку о ОпенЦВ-у, ова плоча има:

  • 1 МБ РОМ
  • 320 КБ РАМ
  • 8 МБ СДРАМ
  • 16 МБ КСПИ

Пошто је подршка за извршавање кода из КСПИ већ додата ОпенЦВ-у, одлучили смо да почнемо са учитавањем целе Ембок ц Кт слике у КСПИ. И ура, све је почело скоро одмах од КСПИ! Али као иу случају ОпенЦВ-а, показало се да ради преспоро.

Пренос Кт-а на СТМ32

Стога смо одлучили да то урадимо на овај начин - прво копирамо слику у КСПИ, затим је учитамо у СДРАМ и одатле извршимо. Од СДРАМ-а је постао мало бржи, али и даље далеко од КЕМУ-а.

Пренос Кт-а на СТМ32

Затим је постојала идеја да се укључи плутајућа тачка - на крају крајева, Кт ради неке прорачуне координата квадрата у анимацији. Покушали смо, али овде нисмо добили никакво видљиво убрзање, иако у Чланак Кт програмери су тврдили да ФПУ даје значајно повећање брзине за „повлачење анимације“ на екрану осетљивом на додир. Може бити знатно мање израчунавања са покретним зарезом у блоковима покрета, а то зависи од конкретног примера.

Најефикаснија идеја је била да се фрамебуффер премести из СДРАМ-а у интерну меморију. Да бисмо то урадили, направили смо димензије екрана не 480к272, већ 272к272. Такође смо смањили дубину боје са А8Р8Г8Б8 на Р5Г6Б5, чиме смо смањили величину једног пиксела са 4 на 2 бајта. Добијена величина бафера оквира је 272 * 272 * 2 = 147968 бајтова. Ово је дало значајно убрзање, можда најуочљивије, анимација је постала скоро глатка.

Најновија оптимизација је била покретање Ембок кода из РАМ-а и Кт кода из СДРАМ-а. Да бисмо то урадили, прво статички повезујемо Ембок заједно са Кт-ом као и обично, али стављамо текст, родата, податке и бсс сегменте библиотеке у КСПИ да бисмо их затим копирали у СДРАМ.

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))

Извршавањем Ембок кода из РОМ-а, такође смо добили приметно убрзање. Као резултат тога, анимација је испала прилично глатка:


На самом крају, припремајући чланак и испробавајући различите конфигурације Ембок-а, показало се да Кт мовеблоцкс одлично функционише од КСПИ са фрамебуффер-ом у СДРАМ-у, а уско грло је била управо величина фрамебуффер-а! Очигледно, да би се превазишао почетни „слидесхов“, било је довољно двоструко убрзање због баналног смањења величине бафера оквира. Али није било могуће постићи такав резултат преношењем само Ембок кода у разне брзе меморије (убрзање није било 2, већ око 2 пута).

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

Ако имате СТМ32Ф7-Дисцовери, можете сами покренути Кт под Ембок-ом. Како се то ради можете прочитати на нашој wiki.

Закључак

Као резултат тога, успели смо да покренемо Кт! Сложеност задатка је, по нашем мишљењу, донекле преувеличана. Наравно, морате узети у обзир специфичности микроконтролера и генерално разумети архитектуру рачунарских система. Резултати оптимизације указују на добро познату чињеницу да уско грло у рачунарском систему није процесор, већ меморија.

Ове године ћемо учествовати на фестивалу ТецхТраин. Тамо ћемо вам рећи детаљније и показати Кт, ОпенЦВ на микроконтролерима и друга наша достигнућа.

Извор: ввв.хабр.цом

Додај коментар