Bonjour ! Nous avons dans notre projet lancé Qt sur STM32F7-Discovery et aimerions en parler. Auparavant, nous avons déjà expliqué comment nous avons réussi à lancer .
Qt est un framework multiplateforme qui inclut non seulement des composants graphiques, mais aussi des éléments tels que QtNetwork, un ensemble de classes pour travailler avec des bases de données, Qt for Automation (y compris pour la mise en œuvre de l'IoT) et bien d'autres. Les développeurs de l'équipe Qt ont prévu l'utilisation de Qt dans des systèmes embarqués, ce qui rend les bibliothèques assez configurables. Cependant, jusqu'à récemment, peu de gens pensaient à porter Qt sur des microcontrôleurs, probablement parce que cela semblait compliqué : Qt est vaste, les MCU sont petits.
D'un autre côté, il existe actuellement des microcontrôleurs conçus pour des applications multimédia et qui surpassent les premiers Pentium. Il y a environ un an sur le blog de Qt est apparu . Les développeurs ont porté Qt sur le système d'exploitation RTEMS et ont exécuté des exemples avec des widgets sur plusieurs cartes fonctionnant sous stm32f7. Cela nous a interpellés. Il était évident, comme le notent les développeurs eux-mêmes, que Qt ralentit sur STM32F7-Discovery. Nous nous sommes demandé si nous pourrions faire fonctionner Qt sous Embox, et non seulement dessiner un widget, mais aussi lancer une animation.
Qt 4.8 a été porté sur Embox depuis longtemps, donc nous avons décidé d'essayer avec celui-ci. Nous avons choisi l'application moveblocks - un exemple d'animation en ressort.
Qt moveblocks sur QEMU
Pour commencer, nous configurons Qt avec le minimum de composants nécessaires pour prendre en charge l'animation. Pour cela, il existe l'option “-qconfig minimal,small,medium …”. Cette option charge un fichier de configuration de Qt avec de nombreux macros - ce qu'il faut inclure / ce qu'il faut désactiver. Après cette option, nous ajoutons d'autres drapeaux à la configuration si nous voulons désactiver encore quelque chose. Voici un exemple de notre .
Pour que Qt fonctionne, il faut ajouter une couche de compatibilité avec le système d'exploitation. L'un des moyens - mettre en œuvre QPA (Qt Platform Abstraction). Nous avons basé notre travail sur le plugin fb_base déjà prêt dans Qt, sur lequel repose le QPA pour Linux. Au final, nous avons obtenu un petit plugin emboxfb, qui fournit à Qt le framebuffer d'Embox, et ensuite il dessine sans aide extérieure.
Voici à quoi ressemble la création d'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();
}
Voici à quoi ressemblera le rafraîchissement
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;
}
Avec l'optimisation du compilateur pour la taille de la mémoire -Os, l'image de la bibliothèque s'est révélée faire 3,5 Mo, ce qui évidemment ne rentre pas dans la mémoire principale du STM32F746. Comme nous l'avons déjà écrit dans notre autre article sur OpenCV, cette carte dispose de :
- 1 Mo de ROM
- 320 Ko de RAM
- 8 Mo de SDRAM
- 16 Mo de QSPI
Étant donné que la prise en charge de l'exécution du code depuis QSPI a déjà été ajoutée pour OpenCV, nous avons décidé de commencer par charger l'image d'Embox avec Qt dans le QSPI dans son intégralité. Et oui, tout a presque immédiatement démarré depuis le QSPI ! Mais comme dans le cas d'OpenCV, il s'est avéré que cela fonctionne trop lentement.

Nous avons donc décidé de procéder ainsi : d'abord nous copions l'image dans le QSPI, puis nous la chargeons dans la SDRAM et nous exécutons à partir de là. C'était un peu plus rapide depuis la SDRAM, mais c'était encore loin de QEMU.

Ensuite, l'idée était d'activer le point flottant - car Qt effectue certains calculs de coordonnées des carrés dans l'animation. Nous avons essayé, mais ici nous n'avons pas obtenu d'accélération visible, bien que les développeurs de Qt aient affirmé que le FPU offre un gain de vitesse significatif pour l'animation de "dragging" sur l'écran tactile. Peut-être que dans moveblocks, il y a considérablement moins de calculs avec des nombres flottants, et cela dépend de l'exemple spécifique.
L'idée la plus efficace a été de transférer le framebuffer de la SDRAM vers la mémoire interne. Pour cela, nous avons défini les dimensions de l'écran non pas à 480×272, mais à 272×272. Nous avons également réduit la profondeur de couleur de A8R8G8B8 à R5G6B5, diminuant ainsi la taille d'un pixel de 4 à 2 octets. Cela nous a donné une taille de framebuffer de 272 * 272 * 2 = 147968 octets. Cela a entraîné un gain de performance significatif, sans doute le plus notable, rendant l'animation presque fluide.
La dernière optimisation consistait à exécuter le code Embox depuis la RAM et Qt depuis la SDRAM. Pour cela, nous avons d'abord lier statiquement Embox avec Qt comme d'habitude, mais nous plaçons les segments text, rodata, data et bss de la bibliothèque dans le QSPI, afin de les copier ensuite dans la 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))
En exécutant le code Embox depuis la ROM, nous avons également obtenu un gain de performance perceptible. Au final, l'animation est devenue suffisamment fluide :

Déjà à la fin, en préparant l'article et en essayant différentes configurations d'Embox, il est apparu que Qt moveblocks fonctionne merveilleusement bien depuis le QSPI avec le framebuffer en SDRAM, et le goulet d'étranglement était justement la taille du framebuffer ! Apparemment, pour surmonter le stade initial de "diaporama", une accélération de 2 fois était suffisante en réduisant simplement la taille du framebuffer. Le simple transfert du code Embox vers différentes mémoires rapides n'a pas permis d'obtenir un tel résultat (l'accélération était de 1,5 fois environ).
Comment essayer par soi-même
Si vous avez un STM32F7-Discovery, vous pouvez exécuter Qt sous Embox vous-même. Vous pouvez lire comment cela se fait sur notre .
Conclusion
Finalement, nous avons réussi à lancer Qt ! La difficulté de la tâche, selon nous, a été quelque peu exagérée. Bien sûr, il faut tenir compte des spécificités des microcontrôleurs et comprendre l'architecture des systèmes de calcul. Les résultats de l'optimisation indiquent un fait bien connu : le point le plus étroit d'un système de calcul, ce n'est pas le processeur, mais la mémoire.
Cette année, nous participerons au festival . Là, nous expliquerons plus en détail et montrerons Qt, OpenCV sur microcontrôleurs et d'autres de nos réalisations.
Source : habr.com
