Goedendag! Wij zijn bezig met een project en hebben Qt draaien op de STM32F7-Discovery en willen daarover vertellen. Eerder hebben we al gepraat over hoe we zijn geslaagd in het starten van .
Qt is een cross-platform framework dat niet alleen grafische componenten omvat, maar ook dingen zoals QtNetwork, een set klassen voor databasebeheer, Qt for Automation (onder andere voor IoT-implementatie) en nog veel meer. De ontwikkelaars van het Qt-team hebben de toepassing van Qt in embedded systemen van tevoren voorzien, waardoor de bibliotheken vrij goed configureerbaar zijn. Tot onlangs had echter weinig iemand nagedacht over het porteren van Qt naar microcontrollers, waarschijnlijk omdat die taak ingewikkeld lijkt ā Qt is groot, MCU's zijn klein.
Anderzijds zijn er op dit moment microcontrollers die zijn ontworpen voor multimedia en die de eerste Pentium-processors overtreffen. Ongeveer een jaar geleden verscheen er een op de Qt-blog. Ontwikkelaars hebben Qt geport naar het RTEMS-besturingssysteem en hebben voorbeelden met widgets op verschillende STM32F7-borden uitgevoerd. Dit wekte onze interesse. Het was merkbaar, en de ontwikkelaars zelf schrijven erover, dat Qt traag is op de STM32F7-Discovery. We waren benieuwd of we Qt onder Embox konden starten, waarbij we niet alleen een widget tekenen, maar ook animatie konden uitvoeren.
Qt 4.8 is al geruime tijd op Embox geport, dus besloten we het daarop te proberen. We kozen de toepassing moveblocks ā een voorbeeld van springende animatie.
Qt moveblocks op QEMU
Om te beginnen configureren we Qt zoveel mogelijk met een minimale verzameling componenten die nodig zijn voor animatieondersteuning. Hiervoor bestaat de optie "-qconfig minimal, small, medium ...". Deze sluit een configuratiebestand in uit Qt met veel macro's - wat in te schakelen / wat uit te schakelen. Na deze optie voegen we andere vlaggen toe aan de configuratie als we nog iets extra's willen uitschakelen. Hier is een voorbeeld van onze .
Om Qt te laten werken, moet er een compat laag met het besturingssysteem worden toegevoegd. Een van de manieren is om QPA (Qt Platform Abstraction) te implementeren. We hebben een reeds bestaande fb_base-plugin uit Qt als basis genomen, waarop de QPA voor Linux draait. Uiteindelijk hebben we een kleine emboxfb-plugin gemaakt, die de framebuffer van Embox aan Qt biedt, en daarna tekent het daar zonder externe hulp.
Zo ziet de creatie van een plugin eruit
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();
}
Zo zal de hertekening eruit zien
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;
}
Uiteindelijk, met de compileroptimalisatie op geheugengrootte -Os, was de bibliotheekversie 3,5 MB, wat natuurlijk niet in het RAM-geheugen van de STM32F746 past. Zoals we al in ons andere artikel over OpenCV hebben geschreven, heeft dit bord:
- 1 MB ROM
- 320 KB RAM
- 8 MB SDRAM
- 16 MB QSPI
Aangezien er al ondersteuning voor het uitvoeren van code vanuit QSPI voor OpenCV was toegevoegd, besloten we te beginnen met het volledig laden van de Embox-image met Qt in QSPI. En hoera, alles startte bijna meteen op uit QSPI! Maar zoals bij OpenCV bleek, werkte het te traag.

Daarom besloten we het zo te doen ā eerst kopiĆ«ren we de image naar QSPI, vervolgens laden we deze in SDRAM en draaien we vanaf daar. Het werd iets sneller vanaf SDRAM, maar het was nog steeds ver van QEMU.

Daarna was er het idee om de floating point-ondersteuning in te schakelen ā want Qt maakt bepaalde berekeningen van de coƶrdinaten van vierkanten in de animatie. We hebben het geprobeerd, maar hier kregen we geen merkbare versnelling, hoewel in de ontwikkelaars van Qt beweerden dat de FPU een aanzienlijke snelheidswinst biedt voor ādragging animationā op een touchscreen. Misschien zijn er bij moveblocks aanzienlijk minder berekeningen met drijvende komma, en dit hangt af van het specifieke voorbeeld.
Het meest effectieve idee bleek om het framebuffer van SDRAM naar het interne geheugen te verplaatsen. Hiervoor hebben we de schermgrootte niet op 480Ć272, maar op 272Ć272 gezet. We hebben ook de kleurdiepte verlaagd van A8R8G8B8 naar R5G6B5, waardoor de grootte van ƩƩn pixel van 4 naar 2 bytes werd verminderd. We kregen een framebuffergrootte van 272 * 272 * 2 = 147968 bytes. Dit zorgde voor een aanzienlijke versnelling, waarschijnlijk het meest merkbare, de animatie werd bijna vloeiend.
De laatste optimalisatie was het uitvoeren van de code van Embox uit RAM, en Qt uit SDRAM. Hiervoor linken we eerst zoals gebruikelijk statisch Embox samen met Qt, maar plaatsen we de segmenten text, rodata, data en bss van de bibliotheek in QSPI, zodat we die later naar SDRAM kunnen kopiƫren.
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))
Door de uitvoering van de code van Embox uit ROM hebben we ook een merkbare versnelling behaald. Uiteindelijk werd de animatie vrij vloeiend:

Al aan het einde, terwijl ik het artikel voorbereidde en verschillende configuraties van Embox uitprobeerde, bleek dat Qt moveblocks uitstekend werkt vanuit QSPI met een framebuffer in SDRAM, terwijl de bottleneck precies de grootte van de framebuffer was! Blijkbaar was het voldoende om de initiƫle 'slideshow' te overwinnen met een versnelling van 2 keer door simpelweg de grootte van de framebuffer te verkleinen. Een dergelijke versnelling door alleen de code van Embox naar verschillende snelle geheugens te verplaatsen, lukte niet (de versnelling was niet 2, maar ongeveer 1.5 keer).
Hoe het zelf te proberen
Als u een STM32F7-Discovery heeft, kunt u Qt zelf onder Embox starten. Hoe dit te doen staat beschreven op onze .
Conclusie
Uiteindelijk is het ons gelukt om Qt te starten! De moeilijkheidsgraad van de taak is naar onze mening iets overschat. Uiteraard moet men rekening houden met de specifics van microcontrollers en over het algemeen de architectuur van rekensystemen begrijpen. De optimalisatieresultaten wijzen op het bekende feit dat het zwakste punt in een rekensysteem niet de processor, maar het geheugen is.
Dit jaar nemen we deel aan het festival . Daar zullen we uitgebreid vertellen en laten zien over Qt, OpenCV op microcontrollers en andere prestaties van ons.
Bron: habr.com
