Dobar dan Mi smo u projektu
Qt je višeplatformski okvir koji uključuje ne samo grafičke komponente, već i stvari kao što su QtNetwork, skup klasa za rad sa bazama podataka, Qt za automatizaciju (uključujući implementaciju IoT-a) i još mnogo toga. Qt tim je bio proaktivan u korišćenju Qt-a u ugrađenim sistemima, tako da su biblioteke prilično konfigurabilne. Međutim, donedavno je malo ljudi razmišljalo o prenošenju Qt-a na mikrokontrolere, vjerovatno zato što se takav zadatak čini teškim – Qt je velik, MCU-ovi mali.
S druge strane, trenutno postoje mikrokontroleri dizajnirani za rad sa multimedijom i superiorniji od prvih Pentiuma. Prije otprilike godinu dana pojavio se Qt blog
Qt 4.8 je već dugo portiran u Embox, pa smo odlučili da ga isprobamo na njemu. Odabrali smo aplikaciju moveblocks - primjer opružne animacije.
Qt pokretni blokovi na QEMU
Za početak, konfigurišemo Qt, ako je moguće, sa minimalnim skupom komponenti potrebnih za podršku animacije. Za ovo postoji opcija “-qconfig minimalno,malo,srednje...”. Povezuje konfiguracionu datoteku iz Qt-a sa mnogim makroima - šta omogućiti/šta onemogućiti. Nakon ove opcije dodajemo druge zastavice u konfiguraciju ako želimo da onemogućimo nešto drugo. Evo primjera našeg
Da bi Qt radio, potrebno je da dodate sloj kompatibilnosti sa operativnim sistemom. Jedan od načina je implementacija QPA (Qt Platform Abstraction). Za osnovu smo uzeli gotovi dodatak fb_base uključen u Qt, na osnovu kojeg radi QPA za Linux. Rezultat je mali dodatak koji se zove emboxfb, koji Qt-u obezbjeđuje Emboxov framebuffer, a zatim ga crta bez ikakve pomoći izvana.
Ovako izgleda kreiranje dodatka
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();
}
A ovako će izgledati precrtavanje
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;
}
Kao rezultat toga, sa omogućenom optimizacijom kompajlera za veličinu memorije -Os, slika biblioteke je bila 3.5 MB, što se naravno ne uklapa u glavnu memoriju STM32F746. Kao što smo već pisali u našem drugom članku o OpenCV-u, ova ploča ima:
- 1 MB ROM
- 320 KB RAM-a
- 8 MB SDRAM
- 16 MB QSPI
Pošto je podrška za izvršavanje koda iz QSPI već dodata OpenCV-u, odlučili smo da počnemo učitavanjem cijele Embox c Qt slike u QSPI. I ura, sve je počelo skoro odmah od QSPI! Ali kao iu slučaju OpenCV-a, pokazalo se da radi presporo.
Stoga smo odlučili da to učinimo na ovaj način - prvo kopiramo sliku u QSPI, zatim je učitamo u SDRAM i odatle izvršimo. Od SDRAM-a je postao malo brži, ali još uvijek daleko od QEMU-a.
Zatim je postojala ideja da se uključi plutajući zarez - na kraju krajeva, Qt radi neke kalkulacije koordinata kvadrata u animaciji. Pokušali smo, ali ovdje nismo dobili nikakvo vidljivo ubrzanje, iako u
Najefikasnija ideja je bila premjestiti framebuffer iz SDRAM-a u internu memoriju. Da bismo to učinili, napravili smo dimenzije ekrana ne 480x272, već 272x272. Takođe smo smanjili dubinu boje sa A8R8G8B8 na R5G6B5, čime smo smanjili veličinu jednog piksela sa 4 na 2 bajta. Rezultirajuća veličina bafera okvira je 272 * 272 * 2 = 147968 bajtova. Ovo je dalo značajno ubrzanje, možda najuočljivije, animacija je postala gotovo glatka.
Najnovija optimizacija je bila pokretanje Embox koda iz RAM-a i Qt koda iz SDRAM-a. Da bismo to uradili, prvo, kao i obično, statički povezujemo Embox zajedno sa Qt-om, ali tekst, rodata, podatke i bss segmente biblioteke stavljamo u QSPI da bismo ih zatim kopirali u 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))
Izvršavanjem Embox koda iz ROM-a, također smo dobili primjetno ubrzanje. Kao rezultat toga, animacija je ispala prilično glatka:
Na samom kraju, pripremajući članak i isprobavajući različite Embox konfiguracije, pokazalo se da Qt moveblocks odlično radi od QSPI sa framebufferom u SDRAM-u, a usko grlo je bila upravo veličina framebuffera! Očigledno, da bi se prevladao početni "slideshow", dvostruko ubrzanje bilo je dovoljno zbog banalnog smanjenja veličine framebuffera. Ali nije bilo moguće postići takav rezultat prijenosom samo Embox koda u razne brze memorije (ubrzanje nije bilo 2, već oko 2 puta).
Kako da probate sami
Ako imate STM32F7-Discovery, možete sami pokrenuti Qt pod Embox-om. Kako se to radi možete pročitati na našoj stranici
zaključak
Kao rezultat toga, uspjeli smo pokrenuti Qt! Složenost zadatka je, po našem mišljenju, pomalo preuveličana. Naravno, morate uzeti u obzir specifičnosti mikrokontrolera i općenito razumjeti arhitekturu računarskih sistema. Rezultati optimizacije ukazuju na dobro poznatu činjenicu da usko grlo u računarskom sistemu nije procesor, već memorija.
Ove godine ćemo učestvovati na festivalu
izvor: www.habr.com