Buongiorno! Siamo nel progetto abbiamo avviato Qt su STM32F7-Discovery e vorremmo parlarne. In precedenza, abbiamo già raccontato come siamo riusciti a lanciare .
Qt è un framework multipiattaforma che include non solo componenti grafici, ma anche cose come QtNetwork, un insieme di classi per lavorare con i database, Qt for Automation (incluso per l'implementazione dell'IoT) e molto altro. Gli sviluppatori del team Qt hanno previsto in anticipo l'uso di Qt nei sistemi embedded, quindi le librerie sono abbastanza ben configurabili. Tuttavia, fino a poco tempo fa, poche persone si erano preoccupate di portare Qt sui microcontrollori, probabilmente perché un compito del genere sembra complesso — Qt è grande, gli MCU sono piccoli.
D'altra parte, attualmente esistono microcontrollori progettati per lavorare con multimedia e superiori ai primi Pentium. Circa un anno fa, è apparso nel blog di Qt . Gli sviluppatori hanno portato Qt su RTEMS e hanno avviato esempi con widget su diverse schede gestite da stm32f7. Questo ci ha interessato. Era evidente, e gli stessi sviluppatori ne parlano, che Qt è lento su STM32F7-Discovery. Ci siamo chiesti se saremmo stati in grado di far funzionare Qt su Embox, non solo disegnando un widget, ma avviando anche un'animazione.
Qt 4.8 è già stato portato su Embox da tempo, quindi abbiamo deciso di provarlo. Abbiamo scelto l'applicazione moveblocks — un esempio di animazione con molla.
Qt moveblocks su QEMU
Per iniziare, configuriamo Qt, se possibile, con il set minimo di componenti richiesti per supportare l'animazione. Per questo esiste l'opzione “-qconfig minimal,small,medium …”. Essa collega un file di configurazione incluso in Qt con molti macro — cosa includere / cosa disattivare. Dopo questa opzione, aggiungiamo alla configurazione altri flag, se vogliamo disattivare ulteriormente qualcos'altro. Ecco un esempio della nostra .
Per far funzionare Qt, è necessario aggiungere uno strato di compatibilità con il sistema operativo. Uno dei modi — implementare QPA (Qt Platform Abstraction). Abbiamo preso come base un plugin già pronto fb_base incluso in Qt, da cui si basa QPA per Linux. Il risultato è stato un piccolo plugin emboxfb, che fornisce a Qt il framebuffer di Embox, e poi disegna lì senza ulteriore aiuto.
Ecco come appare la creazione di un plugin
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();
}
Ecco come apparirà il ridisegno
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;
}
Di conseguenza, con l'ottimizzazione della dimensione di memoria del compilatore -Os, la dimensione della libreria è risultata di 3.5 MB, il che naturalmente non entra nella memoria principale del STM32F746. Come abbiamo già scritto in un altro articolo su OpenCV, su questa scheda sono presenti:
- 1 MB di ROM
- 320 KB di RAM
- 8 MB di SDRAM
- 16 MB di QSPI
Poiché per OpenCV è già stata aggiunta la supporto all'esecuzione del codice da QSPI, abbiamo deciso di iniziare caricando l'immagine di Embox con Qt interamente in QSPI. E finalmente, quasi tutto ha iniziato a funzionare immediatamente da QSPI! Ma come nel caso di OpenCV, si è rivelato funzionare troppo lentamente.

Pertanto, abbiamo deciso di procedere in questo modo: prima copiamo l'immagine in QSPI, poi la carichiamo in SDRAM e ci eseguiamo da lì. Da SDRAM è stato un po' più veloce, ma comunque lontano da QEMU.

In seguito, c'era l'idea di attivare il punto mobile — poiché Qt effettua alcuni calcoli delle coordinate dei quadrati nell'animazione. Abbiamo provato, ma qui non abbiamo ottenuto un aumento visibile, anche se gli sviluppatori di Qt sostenevano che la FPU offre un notevole aumento di velocità per l'animazione di "dragging" su touchscreen. Forse, in moveblocks ci sono sostanzialmente meno calcoli in virgola mobile, e ciò dipende dal caso specifico.
L'idea più efficace è stata quella di trasferire il framebuffer dalla SDRAM alla memoria interna. Per questo motivo, abbiamo impostato le dimensioni dello schermo non a 480×272, ma a 272×272. Abbiamo anche ridotto la profondità del colore da A8R8G8B8 a R5G6B5, riducendo così la dimensione di un pixel da 4 a 2 byte. Abbiamo ottenuto una dimensione del framebuffer di 272 * 272 * 2 = 147968 byte. Questo ha dato un notevole aumento di velocità, probabilmente il più evidente, e l'animazione è diventata quasi fluida.
L'ultima ottimizzazione è stata l'esecuzione del codice Embox dalla RAM, mentre Qt dalla SDRAM. A tal fine, abbiamo prima collegato staticamente Embox insieme a Qt, ma posizioniamo i segmenti text, rodata, data e bss della libreria nella QSPI, per poi copiarli nella 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))
Grazie all'esecuzione del codice Embox dalla ROM abbiamo ottenuto anche un aumento di velocità tangibile. Alla fine l'animazione è risultata abbastanza fluida:

Solo alla fine, preparando l'articolo e provando diverse configurazioni di Embox, è emerso che Qt moveblocks funziona egregiamente anche dalla QSPI con il framebuffer nella SDRAM, e il punto critico era proprio la dimensione del framebuffer! A quanto pare, per superare il primo 'slide show' bastava un aumento di velocità di 2 volte grazie alla banale riduzione delle dimensioni del framebuffer. E raggiungere questo risultato trasferendo solo il codice Embox in diverse memorie veloci non è stato possibile (l'aumento di velocità era non di 2, ma circa di 1.5 volte).
Come provare da soli
Se hai a disposizione un STM32F7-Discovery, puoi avviare Qt sotto Embox da solo. Puoi leggere come fare sul nostro .
Conclusione
Alla fine siamo riusciti a far funzionare Qt! La difficoltà del compito, secondo noi, è stata leggermente esagerata. Naturalmente è necessario tenere conto della specificità dei microcontrollori e comprendere l'architettura dei sistemi di calcolo. I risultati dell'ottimizzazione indicano un fatto noto: il collo di bottiglia in un sistema di calcolo non è il processore, ma la memoria.
Quest'anno parteciperemo al festival . Lì parleremo e mostreremo in dettaglio Qt, OpenCV sui microcontrollori e i nostri altri successi.
Fonte: habr.com
