Guten Tag! Wir haben im Projekt Qt auf dem STM32F7-Discovery gestartet und möchten darüber berichten. Zuvor haben wir bereits beschrieben, wie wir .
Qt ist ein plattformübergreifendes Framework, das nicht nur grafische Komponenten umfasst, sondern auch Dinge wie QtNetwork, eine Klassenbibliothek zur Datenbankarbeit, Qt for Automation (unter anderem zur Implementierung von IoT) und vieles mehr. Die Entwickler des Qt-Teams haben von vornherein die Verwendung von Qt in eingebetteten Systemen berücksichtigt, daher sind die Bibliotheken recht gut konfigurierbar. Bis vor kurzem hat jedoch kaum jemand über das Portieren von Qt auf Mikrocontroller nachgedacht, wahrscheinlich weil diese Aufgabe komplex erscheint – Qt ist umfangreich, die MCUs sind klein.
Andererseits gibt es inzwischen Mikrocontroller, die für Multimedia-Anwendungen entwickelt wurden und die ersten Pentiums übertreffen. Vor etwa einem Jahr erschien in dem Qt-Blog . Die Entwickler haben einen Qt-Port für das RTEMS-Betriebssystem erstellt und Beispiele mit Widgets auf mehreren Boards mit stm32f7 betrieben. Das hat unser Interesse geweckt. Es war offensichtlich, und die Entwickler selbst haben darauf hingewiesen, dass Qt auf dem STM32F7-Discovery langsam läuft. Uns hat interessiert, ob wir Qt unter Embox zum Laufen bringen können, wobei es nicht nur darum geht, ein Widget zu zeichnen, sondern eine Animation zu starten.
In Embox ist bereits seit geraumer Zeit Qt 4.8 portiert, also haben wir beschlossen, es darauf auszuprobieren. Wir haben die Anwendung moveblocks gewählt – ein Beispiel für eine federnde Animation.
Qt moveblocks auf QEMU
Zunächst konfigurieren wir Qt nach Möglichkeit mit einem minimalen Satz an Komponenten, die für die Unterstützung von Animationen erforderlich sind. Dafür gibt es die Option “-qconfig minimal,small,medium …”. Diese lädt eine Konfigurationsdatei aus Qt mit vielen Makros – was ein- bzw. auszuschalten ist. Nach dieser Option fügen wir in die Konfiguration andere Flags hinzu, wenn wir noch etwas zusätzlich deaktivieren möchten. Hier ist ein Beispiel für unsere .
Damit Qt funktionsfähig ist, muss eine Kompatibilitätsschicht für das Betriebssystem hinzugefügt werden. Eine Möglichkeit besteht darin, QPA (Qt Platform Abstraction) zu implementieren. Dazu wurde das bereits vorhandene Plugin fb_base in Qt als Grundlage verwendet, auf dessen Basis das QPA für Linux arbeitet. Das Ergebnis ist ein kleines Plugin emboxfb, welches den Framebuffer von Embox für Qt bereitstellt, und anschließend wird ohne externe Hilfe darauf gezeichnet.
So sieht die Erstellung eines Plugins aus.
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();
}
So wird die Neuzeichnung aussehen
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;
}
Am Ende ergab sich mit aktivierter Compiler-Optimierung für die Speicherkapazität -Os ein Bibliotheksbild von 3,5 MB, was natürlich nicht in den Hauptspeicher des STM32F746 passt. Wie bereits in unserem anderen Artikel zu OpenCV erwähnt, verfügt dieses Board über:
- 1 MB ROM
- 320 KB RAM
- 8 MB SDRAM
- 16 MB QSPI
Da für OpenCV bereits die Unterstützung für die Ausführung von Code aus QSPI hinzugefügt wurde, beschlossen wir, zunächst das Embox-Image mit Qt vollständig in QSPI zu laden. Und hurra, fast alles startete sofort aus QSPI! Aber wie auch im Fall von OpenCV stellte sich heraus, dass es zu langsam arbeitet.

Daher haben wir beschlossen, es so zu machen – zunächst das Image in QSPI zu kopieren, dann in SDRAM zu laden und von dort aus zu arbeiten. Aus SDRAM war es etwas schneller, aber immer noch weit entfernt von QEMU.

Danach hatten wir die Idee, den Fließkomma-Bereich zu aktivieren – schließlich führt Qt einige Berechnungen der Koordinaten von Rechtecken in Animationen durch. Wir haben es ausprobiert, aber hier erhielten wir keinen sichtbaren Geschwindigkeitszuwachs, obwohl in Qt-Entwickler haben bestätigt, dass die FPU eine erhebliche Geschwindigkeitssteigerung bei der "Drag-Animation" auf Touchscreens bietet. Möglicherweise sind die Berechnungen mit Gleitkommazahlen in moveblocks deutlich geringer, und das hängt vom spezifischen Beispiel ab.
Die effektivste Idee war es, den Framebuffer von SDRAM in den internen Speicher zu verschieben. Dazu haben wir die Bildschirmgröße von 480×272 auf 272×272 geändert. Zudem haben wir die Farbtiefe von A8R8G8B8 auf R5G6B5 reduziert, wodurch die Größe eines Pixels von 4 auf 2 Bytes gesenkt wurde. Der Framebuffer hat nun die Größe von 272 * 272 * 2 = 147968 Bytes. Dies brachte eine deutliche Beschleunigung, wohl die bemerkenswerteste, die Animation wurde fast flüssig.
Die letzte Optimierung bestand darin, den Embox-Code aus dem RAM auszuführen und Qt aus SDRAM. Dazu haben wir wie gewohnt Embox zusammen mit Qt statisch verlinkt, aber die Segmente text, rodata, data und bss der Bibliothek wurden in QSPI platziert, um sie anschließend in SDRAM zu kopieren.
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))
Durch die Ausführung des Embox-Codes aus dem ROM haben wir ebenfalls eine spürbare Beschleunigung erzielt. Am Ende wurde die Animation ziemlich flüssig:

Kurz vor Abschluss des Artikels, während ich verschiedene Konfigurationen von Embox ausprobierte, stellte ich fest, dass Qt moveblocks hervorragend von QSPI mit einem Framebuffer in SDRAM funktionierte. Der Flaschenhals war tatsächlich die Größe des Framebuffers! Anscheinend genügte es, die Größe des Framebuffers zu reduzieren, um die anfängliche „Diashow“ mit einer Beschleunigung von 2x zu überwinden. Es gelang jedoch nicht, diesen Effekt allein durch den Transfer des Embox-Codes in verschiedene schnelle Speicher zu erreichen (die Beschleunigung betrug nicht 2x, sondern etwa 1,5x).
Wie Sie es selbst ausprobieren können
Wenn Sie ein STM32F7-Discovery besitzen, können Sie Qt unter Embox selbst ausführen. Eine Anleitung dazu finden Sie auf unserem .
Fazit
Schließlich ist es uns gelungen, Qt zum Laufen zu bringen! Die Komplexität der Aufgabe scheint uns etwas übertrieben zu sein. Natürlich muss man die Spezifikationen der Mikrokontroller berücksichtigen und generell die Architektur von Computersystemen verstehen. Die Optimierungsergebnisse weisen auf die bekannte Tatsache hin, dass der Engpass in einem Computersystem nicht der Prozessor, sondern der Speicher ist.
In diesem Jahr werden wir am Festival teilnehmen . Dort werden wir genauer über Qt, OpenCV auf Mikrokontrollern und andere unsere Erfolge berichten und demonstrieren.
Quelle: habr.com
