Portearje Qt nei STM32

Portearje Qt nei STM32Goeiemiddei Wy binne yn it projekt Embox lansearre Qt op STM32F7-Discovery en soe graach prate oer it. Earder hawwe wy al ferteld hoe't wy it slagge om te lansearjen OpenCV.

Qt is in cross-platfoarm ramt dat omfiemet net allinnich grafyske komponinten, mar ek sokke dingen as QtNetwork, in set fan klassen foar in wurk mei databases, Qt foar automatisearring (ynklusyf foar IoT ymplemintaasje) en folle mear. It Qt-team hat proaktyf west oer it brûken fan Qt yn ynbêde systemen, sadat de biblioteken frij konfigurearber binne. Lykwols, oant koartlyn tochten in pear minsken oer it portearjen fan Qt nei mikrocontrollers, wierskynlik om't sa'n taak lestich liket - Qt is grut, MCU's binne lyts.

Oan 'e oare kant binne d'r op it stuit mikrocontrollers ûntworpen om te wurkjen mei multimedia en superieur oan' e earste Pentiums. Sawat in jier lyn ferskynde it Qt-blog post. De ûntwikkelders makken in haven fan Qt foar it RTEMS OS, en lansearre foarbylden mei widgets op ferskate boards dy't stm32f7 rinne. Dit ynteressearre ús. It wie opfallend, en de ûntwikkelders sels skriuwe deroer, dat Qt stadich is op 'e STM32F7-Discovery. Wy fregen ús ôf oft wy koenen rinne Qt ûnder Embox, en net allinne tekenje in widget, mar rinne in animaasje.

Qt 4.8 is in lange tiid nei Embox porteare, dus wy besletten it derop te besykjen. Wy keas de moveblocks-applikaasje - in foarbyld fan springende animaasje.

Qt moveblocks op QEMUPortearje Qt nei STM32

Om te begjinnen, wy konfigurearje Qt, as it mooglik is, mei de minimale set fan komponinten nedich foar in stipe animation. Hjirfoar is d'r in opsje "-qconfig minimaal, lyts, medium ...". It ferbynt in konfiguraasjetriem út Qt mei in protte makro - wat te skeakeljen / wat te skeakeljen. Nei dizze opsje foegje wy oare flaggen ta oan 'e konfiguraasje as wy wat oars wolle útskeakelje. Hjir is in foarbyld fan ús konfiguraasje.

Om Qt te wurkjen, moatte jo in OS-kompatibiliteitslaach tafoegje. Ien manier is in útfiere QPA (Qt Platform Abstraksje). Wy namen as basis de klearmakke fb_base-plugin opnommen yn Qt, op basis wêrfan QPA foar Linux wurket. It resultaat is in lyts plugin neamd emboxfb, dy't Qt foarsjocht mei de framebuffer fan Embox, en dan tekenet it dêr sûnder help fan bûten.

Dit is wat it meitsjen fan in plugin liket

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 sa sil de wertekening der útsjen

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 gefolch, mei de gearstaller-optimalisaasje foar ûnthâldgrutte -Os ynskeakele, die bliken dat de biblioteekôfbylding 3.5 MB wie, wat fansels net past yn it haadûnthâld fan 'e STM32F746. Lykas wy al skreaun hawwe yn ús oare artikel oer OpenCV, hat dit boerd:

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

Sûnt stipe foar it útfieren fan koade fan QSPI is al tafoege oan OpenCV, hawwe wy besletten om te begjinnen mei it laden fan de hiele Embox c Qt-ôfbylding yn QSPI. En hoera, alles begon hast fuortendaliks fan QSPI! Mar lykas yn it gefal fan OpenCV, die bliken dat it te stadich wurket.

Portearje Qt nei STM32

Dêrom besleaten wy it op dizze manier te dwaan - earst kopiearje wy de ôfbylding nei QSPI, laden it dan yn SDRAM en útfiere dêrwei. Fan SDRAM waard it in bytsje flugger, mar noch fier fan QEMU.

Portearje Qt nei STM32

Folgjende, der wie in idee om in driuwend punt - na docht Qt guon berekkeningen fan de koördinaten fan pleinen yn animaasje. Wy besochten, mar hjir krigen wy gjin sichtbere fersnelling, hoewol yn artikel Qt-ûntwikkelders bewearden dat FPU jout in signifikante ferheging fan snelheid foar "slepen animaasje" op touchscreen. D'r kinne signifikant minder driuwende puntberekkeningen wêze yn bewegingsblokken, en dit hinget ôf fan it spesifike foarbyld.

It meast effektive idee wie om de framebuffer fan SDRAM nei ynterne ûnthâld te ferpleatsen. Om dit te dwaan, makken wy de skermôfmjittings net 480x272, mar 272x272. Wy hawwe ek de kleurdjipte ferlege fan A8R8G8B8 nei R5G6B5, sadat de grutte fan ien piksel fan 4 nei 2 bytes fermindere. De resultearjende framebuffergrutte is 272 * 272 * 2 = 147968 bytes. Dit joech in wichtige fersnelling, miskien it meast opfallend, de animaasje waard hast glêd.

De lêste optimalisaasje wie in útfiere Embox koade út RAM en Qt koade út SDRAM. Om dit te dwaan, wy earst, lykas gewoanlik, statysk keppele Embox tegearre mei Qt, mar wy pleatse de tekst, rodata, gegevens en bss segminten fan de bibleteek yn QSPI om dan kopiearje it nei 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))

Troch de Embox-koade út te fieren fan ROM, krigen wy ek in merkbere fersnelling. As gefolch, de animaasje draaide frij glêd:


Oan 'e ein, wylst it tarieden fan it artikel en besykje ferskillende Embox konfiguraasjes, die bliken dat Qt moveblocks wurket great út QSPI mei in framebuffer yn SDRAM, en de knelpunt wie krekt de grutte fan 'e framebuffer! Blykber, om de earste "slideshow" te oerwinnen, wie in 2-fâldige fersnelling genôch troch in banale reduksje fan 'e framebuffergrutte. Mar it wie net mooglik om sa'n resultaat te berikken troch allinich de Embox-koade oer te setten nei ferskate rappe oantinkens (de fersnelling wie net 2, mar sawat 1.5 kear).

Hoe kinne jo it sels besykje

As jo ​​in STM32F7-Discovery, kinne jo rinne Qt ûnder Embox sels. Jo kinne lêze hoe't dit dien wurdt op ús wiki.

konklúzje

As gefolch, wy slagge in lansearring Qt! De kompleksiteit fan de taak is neffens ús wat oerdreaun. Fansels moatte jo rekken hâlde mei de spesifikaasjes fan mikrocontrollers en yn 't algemien de arsjitektuer fan kompjûtersystemen begripe. De optimalisaasjeresultaten wize op it bekende feit dat de knelpunt yn in komputersysteem net de prosessor is, mar it ûnthâld.

Dit jier dogge wy mei oan it festival TechTrain. Dêr sille wy jo yn mear detail fertelle en Qt, OpenCV op mikrocontrollers en ús oare prestaasjes sjen litte.

Boarne: www.habr.com

Add a comment