Oordra Qt na STM32

Oordra Qt na STM32Goeie middag Ons is in die projek Embos Qt op STM32F7-Discovery bekendgestel en wil graag daaroor praat. Ons het vroeër reeds vertel hoe ons dit reggekry het om te begin OpenCV.

Qt is 'n kruisplatform-raamwerk wat nie net grafiese komponente insluit nie, maar ook dinge soos QtNetwork, 'n stel klasse om met databasisse te werk, Qt vir outomatisering (insluitend IoT-implementering) en nog baie meer. Die ontwikkelaars van die Qt-span het die gebruik van Qt in ingebedde stelsels voorsien, so die biblioteke is redelik goed konfigureerbaar. Tot onlangs het min mense egter daaraan gedink om Qt na mikrobeheerders oor te dra, waarskynlik omdat so 'n taak moeilik lyk - Qt is groot, MCU's is klein.

Aan die ander kant, op die oomblik is daar mikrobeheerders wat ontwerp is om met multimedia te werk en die eerste Pentiums te oortref. Het sowat 'n jaar gelede op die Qt-blog verskyn post. Die ontwikkelaars het 'n poort van Qt onder RTEMS OS gemaak, en het voorbeelde met widgets op verskeie borde uitgevoer met stm32f7. Ons stel belang hierin. Dit was opvallend, en die ontwikkelaars skryf self daaroor, dat Qt stadiger word op STM32F7-Discovery. Ons het gewonder of ons Qt onder Embox kan laat loop, en nie net 'n legstuk kan teken nie, maar 'n animasie kan laat loop.

Qt 4.8 is al lank na Embox oorgedra, so ons het besluit om dit daarop te probeer. Ons het die moveblocks-toepassing gekies - 'n voorbeeld van veerkragtige animasie.

Qt-skuifblokke op QEMUOordra Qt na STM32

Om mee te begin, stel ons Qt op met die minimum stel komponente wat nodig is om animasie te ondersteun, indien moontlik. Daar is 'n opsie "-qconfig minimaal, klein, medium ..." hiervoor. Dit bevat 'n konfigurasielêer van Qt met baie makro's - wat om te aktiveer / wat om te deaktiveer. Na hierdie opsie voeg ons ander vlae by die konfigurasie as ons iets anders addisioneel wil deaktiveer. Hier is 'n voorbeeld van ons opset.

Om Qt te laat werk, moet jy 'n OS-versoenbaarheidslaag byvoeg. Een manier is om QPA (Qt Platform Abstraction) te implementeer. Die klaargemaakte fb_base-inprop as deel van Qt is as basis geneem, op grond waarvan QPA vir Linux werk. Die resultaat is 'n klein emboxfb-inprop wat Qt van Embox se raambuffer voorsien, en dan trek dit daarheen sonder hulp van buite.

Dit is hoe die inprop lyk

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();
}

En dit is hoe die hertekening sal lyk

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;
}

As gevolg hiervan, met die samestelleroptimalisering vir geheuegrootte geaktiveer -Os, het die biblioteekbeeld 3.5 MB geblyk te wees, wat natuurlik nie in die hoofgeheue van die STM32F746 pas nie. Soos ons in ons ander artikel oor OpenCV geskryf het, het hierdie bord:

  • 1 MB ROM
  • 320 KB RAM
  • 8 MB SDRAM
  • 16 MB QSPI

Aangesien ondersteuning vir die uitvoering van kode vanaf QSPI reeds vir OpenCV bygevoeg is, het ons besluit om te begin deur die hele Embbox-prent met Qt in QSPI te laai. En hoera, alles het byna dadelik vanaf QSPI begin! Maar soos in die geval van OpenCV, het dit geblyk te stadig te wees.

Oordra Qt na STM32

Daarom het ons besluit om dit te doen - ons kopieer eers die prent na QSPI, dan laai ons dit in SDRAM en voer dit van daar af uit. Van SDRAM af het dit 'n bietjie vinniger geword, maar steeds ver van QEMU af.

Oordra Qt na STM32

Dan was daar die idee om 'n drywende punt in te sluit - Qt doen immers 'n paar berekeninge van die koördinate van die vierkante in die animasie. Ons het probeer, maar hier het ons nie 'n sigbare versnelling gekry nie, hoewel in Artikel Die Qt-ontwikkelaars het beweer dat die FPU 'n aansienlike spoedverhoging bied om animasies op die raakskerm te sleep. Daar kan aansienlik minder swaaipuntberekeninge in skuifblokke wees, en dit hang af van die spesifieke voorbeeld.

Die idee om die raambuffer van SDRAM na interne geheue oor te dra, was die doeltreffendste. Om dit te doen, het ons die skermgrootte nie 480x272 gemaak nie, maar 272x272. Ons het ook die kleurdiepte van A8R8G8B8 na R5G6B5 verlaag, en sodoende die grootte van een pixel van 4 tot 2 grepe verminder. Ons het die raambuffergrootte 272 * 272 * 2 = 147968 grepe gekry. Dit het 'n aansienlike versnelling gegee, miskien die mees opvallende, die animasie het amper glad geword.

Die laaste optimalisering was die uitvoering van Embox-kode vanaf RAM, en Qt vanaf SDRAM. Om dit te doen, koppel ons eers, soos gewoonlik, Embox staties saam met Qt, maar ons plaas die teks-, rodata-, data- en bss-segmente van die biblioteek in QSPI om dit later na SDRAM te kopieer.

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

Deur die Embox-kode vanaf die ROM uit te voer, het ons ook 'n merkbare versnelling gekry. As gevolg hiervan het die animasie redelik glad geblyk:


Reeds heel aan die einde, met die voorbereiding van die artikel en probeer verskillende konfigurasies van Embox, het dit geblyk dat Qt moveblocks uitstekend werk vanaf QSPI met 'n raambuffer in SDRAM, en die bottelnek was presies die grootte van die raambuffer! Blykbaar, om die aanvanklike "skyfievertoning" te oorkom, was 'n 2-voudige versnelling genoeg as gevolg van 'n banale vermindering in die grootte van die raambuffer. Maar dit was nie moontlik om so 'n resultaat te bereik deur slegs die Embox-kode na verskeie vinnige herinneringe oor te dra nie (die versnelling was nie 2 nie, maar ongeveer 1.5 keer).

Hoe om dit self te probeer

As jy STM32F7-Discovery het, kan jy self Qt onder Embox laat loop. Jy kan lees hoe dit gedoen word op ons вики.

Gevolgtrekking

As gevolg hiervan het ons daarin geslaag om Qt! Die kompleksiteit van die taak is na ons mening ietwat oordrewe. U moet natuurlik die besonderhede van mikrobeheerders in ag neem en die argitektuur van rekenaarstelsels oor die algemeen verstaan. Die optimaliseringsresultate dui op die bekende feit dat die bottelnek in 'n rekenaarstelsel nie die verwerker is nie, maar die geheue.

Hierdie jaar gaan ons aan die fees deelneem Tegniese trein. Daar sal ons in meer besonderhede vertel en Qt, OpenCV op mikrobeheerders en ons ander prestasies wys.

Bron: will.com

Voeg 'n opmerking