Qt STM32ra eramatea

Qt STM32ra eramateaArratsalde on Proiektuan gaude Embox Qt abiarazi zuen STM32F7-Discovery-n eta horri buruz hitz egin nahiko nuke. Lehenago, jada kontatu genuen nola lortu genuen martxan jartzea OpenCV.

Qt plataforma anitzeko esparrua da, osagai grafikoak ez ezik, QtNetwork, datu-baseekin lan egiteko klase multzo bat, Qt for Automation (IoT inplementazioa barne) eta askoz gehiago barne hartzen dituena. Qt taldea proaktiboa izan da Qt sistema txertatuetan erabiltzeko, beraz liburutegiak nahiko konfiguragarriak dira. Hala ere, duela gutxi arte, jende gutxik pentsatu zuen Qt mikrokontrolagailuetara eramatea, ziurrenik zeregin hori zaila dirudielako - Qt handia da, MCUak txikiak dira.

Bestalde, momentu honetan multimediarekin lan egiteko diseinatutako mikrokontrolagailuak daude eta lehen Pentium-en gainetik. Duela urtebete inguru Qt bloga agertu zen post. Garatzaileek Qt-ren ataka bat egin zuten RTEMS OS-rako, eta stm32f7 exekutatzen duten hainbat plaketan widgetekin adibideak jarri zituzten. Hau interesatzen zitzaigun. Nabarmena zen, eta garatzaileek beraiek idazten dute horri buruz, Qt motela dela STM32F7-Discovery-n. Embox-en Qt exekutatu genezakeen galdetzen ari ginen, eta ez widget bat bakarrik marraztu, animazio bat exekutatu baizik.

Qt 4.8 emboxera eraman da denbora luzez, beraz, bertan probatzea erabaki dugu. Moveblocks aplikazioa aukeratu dugu, animazio udaberriko adibide bat.

Qt moveblocks QEMU-nQt STM32ra eramatea

Hasteko, Qt konfiguratuko dugu, ahal bada, animazioa onartzen duen gutxieneko osagai multzoarekin. Horretarako β€œ-qconfig minimal,small, medium...” aukera dago. Qt-eko konfigurazio fitxategi bat makro askorekin konektatzen du - zer gaitu / zer desgaitu. Aukera honen ondoren, beste bandera batzuk gehitzen dizkiogu konfigurazioari, beste zerbait desgaitu nahi badugu. Hona hemen gure adibide bat konfigurazioa.

Qt funtziona dezan, OS bateragarritasun geruza bat gehitu behar duzu. Modu bat QPA (Qt Platform Abstraction) ezartzea da. Qt-en barne dagoen prest egindako fb_base plugina hartu genuen oinarritzat, Linux-erako QPA-k funtzionatzen duena. Emaitza emboxfb izeneko plugin txiki bat da, Qt-i Embox-en framebuffer-a ematen diona, eta gero hor marrazten du kanpoko laguntzarik gabe.

Hau da plugin bat sortzearen itxura

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();
}

Eta hauxe izango da birmarrazketa

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;
}

Ondorioz, konpiladorearen optimizazioa memoria-tamainaren -Os gaituta, liburutegiaren irudia 3.5 MB-koa izan da, eta hori ez da STM32F746-ren memoria nagusian sartzen noski. OpenCV-ri buruzko beste artikulu batean jada idatzi genuen bezala, taula honek honako hauek ditu:

  • 1 MB ROM
  • 320 KB RAM
  • 8 MB SDRAM
  • 16 MB QSPI

QSPIren kodea exekutatzeko laguntza OpenCV-ra dagoeneko gehitu denez, Embox c Qt irudi osoa QSPIn kargatzen hastea erabaki dugu. Eta tira, dena ia berehala hasi zen QSPItik! Baina OpenCV-ren kasuan bezala, polikiegi funtzionatzen duela ikusi zen.

Qt STM32ra eramatea

Hori dela eta, modu honetan egitea erabaki dugu - lehenik eta behin irudia QSPIra kopiatzen dugu, ondoren SDRAM-en kargatu eta hortik exekutatzen dugu. SDRAMetik pixka bat azkarragoa bihurtu zen, baina oraindik QEMUtik urrun.

Qt STM32ra eramatea

Ondoren, koma mugikor bat sartzeko ideia bat zegoen; azken finean, Qt-ek karratuen koordenatuen kalkulu batzuk egiten ditu animazioan. Saiatu ginen, baina hemen ez genuen azelerazio ikusgarririk lortu, nahiz eta Artikulu Qt garatzaileek esan zuten FPUk abiadura handitzen duela ukipen-pantailan "animazioa arrastatzeagatik". Mugimendu-blokeetan koma mugikorreko kalkulu gutxiago egon daitezke, eta hori adibide zehatzaren araberakoa da.

Ideia eraginkorrena izan zen framebuffer-a SDRAMetik barne memoriara eramatea. Horretarako, pantailaren neurriak ez 480x272 egin ditugu, 272x272 baizik. Kolore-sakonera ere jaitsi dugu A8R8G8B8-tik R5G6B5-era, horrela pixel baten tamaina 4 bytetik 2ra murriztuz. Ondorioz, framebuffer tamaina 272 * 272 * 2 = 147968 byte da. Horrek azelerazio nabarmena eman zuen, agian nabarmenena, animazioa ia leuna bihurtu zen.

Azken optimizazioa Embbox kodea RAMetik eta Qt kodea SDRAMetik exekutatu zen. Horretarako, lehenik eta behin, ohi bezala, estatikoki lotzen dugu Embbox Qt-ekin, baina liburutegiko testu, rodata, datu eta bss segmentuak QSPIn jartzen ditugu, gero SDRAMera kopiatzeko.

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))

Embox kodea ROMetik exekutatuta, azelerazio nabaria ere jaso dugu. Ondorioz, animazioa nahiko leuna izan zen:


Bukaeran, artikulua prestatzen eta Emboxen konfigurazio desberdinak probatzean, Qt moveblocks-ek QSPI-tik bikain funtzionatzen du SDRAM-eko framebuffer batekin, eta botila-lepoa framebuffer-aren tamainakoa zela! Antza denez, hasierako "diaporama" gainditzeko, nahikoa zen bi aldiz azelerazioa, framebuffer-aren tamainaren murrizketa hutsalaren ondorioz. Baina ezin izan zen horrelako emaitzarik lortu Embox kodea soilik hainbat memoria azkar transferituz (azelerazioa ez zen 2, 2 aldiz inguru).

Zeuk nola probatu

STM32F7-Discovery bat baduzu, Qt exekutatu dezakezu Embbox azpian. Hau nola egiten den irakur dezakezu gure webgunean wikia.

Ondorioa

Ondorioz, Qt! Zereginaren konplexutasuna, gure ustez, gehiegizkoa da. Jakina, mikrokontrolagailuen berezitasunak kontuan hartu behar dituzu eta, oro har, sistema informatikoen arkitektura ulertu behar duzu. Optimizazio emaitzek jakina denez, sistema informatiko baten botila-lepoa ez da prozesadorea, memoria baizik.

Aurten jaialdian parte hartuko dugu TechTrain. Bertan zehatzago esango dizugu eta Qt, OpenCV mikrokontrolagailuetan eta gure beste lorpenak erakutsiko ditugu.

Iturria: www.habr.com

Gehitu iruzkin berria