Hyvää iltapäivää Olemme mukana projektissa
Qt on monialustainen kehys, joka sisältää paitsi graafisia komponentteja, myös sellaisia asioita kuin QtNetwork, tietokantojen kanssa työskentelyyn tarkoitettujen luokkien sarja, Qt for Automation (mukaan lukien IoT-toteutus) ja paljon muuta. Qt-tiimi on ollut ennakoivasti käyttänyt Qt:tä sulautetuissa järjestelmissä, joten kirjastot ovat melko konfiguroitavissa. Kuitenkin viime aikoihin asti harvat ihmiset ajattelivat Qt:n siirtämistä mikro-ohjaimiin, luultavasti siksi, että tällainen tehtävä näyttää vaikealta - Qt on suuri, MCU:t ovat pieniä.
Toisaalta tällä hetkellä on olemassa mikrokontrollereita, jotka on suunniteltu toimimaan multimedian kanssa ja jotka ovat parempia kuin ensimmäiset Pentiumit. Noin vuosi sitten ilmestyi Qt-blogi
Qt 4.8 on siirretty Emboxiin pitkään, joten päätimme kokeilla sitä siinä. Valitsimme Moveblocks-sovelluksen - esimerkki joustavasta animaatiosta.
Qt-siirtolohkot QEMU:ssa
Aluksi määritämme Qt:n, jos mahdollista, animaation tukemiseen vaadittavien komponenttien vähimmäisjoukolla. Tätä varten on vaihtoehto "-qconfig minimal,small,medium...". Se yhdistää Qt:n asetustiedoston moniin makroihin - mitä ottaa käyttöön / mitä poistaa. Tämän vaihtoehdon jälkeen lisäämme kokoonpanoon muita lippuja, jos haluamme poistaa jonkin muun käytöstä. Tässä on esimerkki meidän
Jotta Qt toimisi, sinun on lisättävä käyttöjärjestelmän yhteensopivuuskerros. Yksi tapa on toteuttaa QPA (Qt Platform Abstraction). Otimme pohjaksi Qt:ssä olevan valmiin fb_base-liitännäisen, jonka pohjalta QPA for Linux toimii. Tuloksena on pieni laajennus nimeltä emboxfb, joka tarjoaa Qt:lle Emboxin kehyspuskurin ja sitten se piirtyy sinne ilman ulkopuolista apua.
Tältä laajennuksen luominen näyttää
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();
}
Ja tältä uudelleenpiirustus tulee näyttämään
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;
}
Seurauksena oli, että kääntäjän muistin koon -Os optimoinnin ollessa käytössä kirjaston kuvaksi tuli 3.5 MB, mikä ei tietenkään mahdu STM32F746:n päämuistiin. Kuten jo kirjoitimme toisessa OpenCV-artikkelissamme, tällä taululla on:
- 1 MB ROM
- 320KB RAM
- 8 Mt SDRAM
- 16 Mt QSPI
Koska tuki QSPI:n koodin suorittamiselle on jo lisätty OpenCV:hen, päätimme aloittaa lataamalla koko Embox c Qt -kuvan QSPI:hen. Ja hurraa, kaikki alkoi melkein heti QSPI:stä! Mutta kuten OpenCV:n tapauksessa, kävi ilmi, että se toimii liian hitaasti.
Siksi päätimme tehdä sen tällä tavalla - kopioimme ensin kuvan QSPI: hen, lataamme sen SDRAM-muistiin ja suoritamme sieltä. SDRAMista tuli hieman nopeampi, mutta silti kaukana QEMU:sta.
Seuraavaksi oli ajatus sisällyttää liukuluku - Qthan sentään tekee joitain laskelmia neliöiden koordinaateista animaatiossa. Yritimme, mutta täällä emme saaneet näkyvää kiihtyvyyttä, vaikka sisään
Tehokkain idea oli siirtää kehyspuskuri SDRAM-muistista sisäiseen muistiin. Tätä varten teimme näytön mitoiksi ei 480x272, vaan 272x272. Lasimme myös värisyvyyttä A8R8G8B8:sta R5G6B5:een, mikä pienensi yhden pikselin kokoa 4 tavusta 2 tavuun. Tuloksena oleva kehyspuskurin koko on 272 * 272 * 2 = 147968 tavua. Tämä antoi merkittävän kiihtyvyyden, ehkä huomattavimmin animaatiosta tuli lähes tasainen.
Viimeisin optimointi oli suorittaa Embox-koodi RAM-muistista ja Qt-koodi SDRAM-muistista. Tätä varten yhdistämme ensin staattisesti Emboxin tuttuun tapaan Qt:hen, mutta sijoitamme kirjaston teksti-, rodata-, data- ja bss-segmentit QSPI:hen kopioidaksemme sen SDRAM-muistiin.
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))
Suorittamalla Embox-koodin ROM:lta saimme myös huomattavan kiihtyvyyden. Tämän seurauksena animaatio osoittautui melko sujuvaksi:
Aivan lopussa artikkelia valmistellessa ja erilaisia Embox-kokoonpanoja kokeiltaessa kävi ilmi, että Qt moveblocks toimii loistavasti QSPI:stä SDRAM:n framebufferilla ja pullonkaula oli juuri framebufferin kokoinen! Ilmeisesti alkuperäisen "diaesityksen" voittamiseksi 2-kertainen kiihtyvyys riitti kehyspuskurin koon banaalista pienennyksestä. Mutta tällaista tulosta ei voitu saavuttaa siirtämällä vain Embox-koodia erilaisiin nopeisiin muisteihin (kiihtyvyys ei ollut 2, vaan noin 1.5-kertainen).
Kuinka kokeilla sitä itse
Jos sinulla on STM32F7-Discovery, voit suorittaa Qt:n Emboxin alla itse. Voit lukea kuinka tämä tehdään meidän sivuiltamme
Johtopäätös
Tämän seurauksena onnistuimme käynnistämään Qt! Tehtävän monimutkaisuus on mielestämme hieman liioiteltua. Luonnollisesti sinun on otettava huomioon mikro-ohjainten erityispiirteet ja yleisesti ymmärrettävä tietokonejärjestelmien arkkitehtuuri. Optimointitulokset viittaavat hyvin tunnettuun tosiasiaan, että laskentajärjestelmän pullonkaula ei ole prosessori, vaan muisti.
Tänä vuonna osallistumme festivaaleille
Lähde: will.com