Kuhamisha Qt kwa STM32

Kuhamisha Qt kwa STM32Habari za mchana Tuko kwenye mradi Embox ilizindua Qt kwenye STM32F7-Discovery na ningependa kuizungumzia. Hapo awali, tulielezea jinsi tulivyoweza kuzindua OpenCV.

Qt ni mfumo wa majukwaa mtambuka ambayo inajumuisha sio tu vijenzi vya picha, lakini pia vitu kama vile QtNetwork, seti ya madarasa ya kufanya kazi na hifadhidata, Qt ya Uendeshaji (pamoja na utekelezaji wa IoT) na mengi zaidi. Timu ya Qt imekuwa makini kuhusu kutumia Qt katika mifumo iliyopachikwa, kwa hivyo maktaba zinaweza kusanidiwa kabisa. Walakini, hadi hivi majuzi, watu wachache walifikiria juu ya kuhamisha Qt kwa vidhibiti vidogo, labda kwa sababu kazi kama hiyo inaonekana kuwa ngumu - Qt ni kubwa, MCU ni ndogo.

Kwa upande mwingine, kwa sasa kuna microcontrollers iliyoundwa kufanya kazi na multimedia na bora kuliko Pentiums ya kwanza. Takriban mwaka mmoja uliopita, blogu ya Qt ilionekana chapisho. Watengenezaji walitengeneza bandari ya Qt kwa ajili ya Mfumo wa Uendeshaji wa RTEMS, na wakazindua mifano yenye wijeti kwenye mbao kadhaa zinazotumia stm32f7. Hii ilituvutia. Ilionekana, na watengenezaji wenyewe wanaandika juu yake, kwamba Qt ni polepole kwenye STM32F7-Discovery. Tulikuwa tunashangaa kama tunaweza kuendesha Qt chini ya Embox, na si tu kuchora wijeti, lakini kuendesha uhuishaji.

Qt 4.8 imetumwa kwa Embox kwa muda mrefu, kwa hivyo tuliamua kuijaribu. Tulichagua programu ya vizuizi - mfano wa uhuishaji wa kuvutia.

Vizuizi vya Qt kwenye QEMUKuhamisha Qt kwa STM32

Kuanza, tunasanidi Qt, ikiwezekana, na seti ya chini ya vipengele vinavyohitajika kusaidia uhuishaji. Kwa hili kuna chaguo "-qconfig ndogo, ndogo, kati ...". Inaunganisha faili ya usanidi kutoka Qt na macros nyingi - nini cha kuwezesha / nini cha kuzima. Baada ya chaguo hili, tunaongeza bendera zingine kwenye usanidi ikiwa tunataka kuzima kitu kingine. Hapa kuna mfano wetu usanidi.

Ili Qt ifanye kazi, unahitaji kuongeza safu ya uoanifu ya OS. Njia moja ni kutekeleza QPA (Qt Platform Abstraction). Tulichukua kama msingi programu-jalizi iliyotengenezwa tayari ya fb_base iliyojumuishwa kwenye Qt, kwa msingi ambao QPA ya Linux hufanya kazi. Matokeo yake ni programu-jalizi ndogo inayoitwa emboxfb, ambayo hutoa Qt na fremu ya Embox, na kisha huchota hapo bila usaidizi wowote wa nje.

Hivi ndivyo kuunda programu-jalizi inaonekana

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

Na hii ndio jinsi uchoraji upya utaonekana

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

Kama matokeo, pamoja na uboreshaji wa mkusanyaji kwa saizi ya kumbukumbu -Os imewezeshwa, picha ya maktaba iligeuka kuwa 3.5 MB, ambayo bila shaka haifai katika kumbukumbu kuu ya STM32F746. Kama tulivyoandika tayari katika nakala yetu nyingine kuhusu OpenCV, bodi hii ina:

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

Kwa kuwa usaidizi wa kutekeleza msimbo kutoka QSPI tayari umeongezwa kwa OpenCV, tuliamua kuanza kwa kupakia picha nzima ya Embox c Qt kwenye QSPI. Na haraka, kila kitu kilianza mara moja kutoka QSPI! Lakini kama ilivyo kwa OpenCV, iliibuka kuwa inafanya kazi polepole sana.

Kuhamisha Qt kwa STM32

Kwa hivyo, tuliamua kuifanya kwa njia hii - kwanza tunakili picha hiyo kwa QSPI, kisha kuipakia kwenye SDRAM na kutekeleza kutoka hapo. Kutoka SDRAM ikawa kasi kidogo, lakini bado iko mbali na QEMU.

Kuhamisha Qt kwa STM32

Ifuatayo, kulikuwa na wazo la kujumuisha sehemu inayoelea - baada ya yote, Qt hufanya mahesabu kadhaa ya viwianishi vya miraba katika uhuishaji. Tulijaribu, lakini hapa hatukupata kasi yoyote inayoonekana, ingawa ndani Ibara ya Wasanidi wa Qt walidai kuwa FPU inatoa ongezeko kubwa la kasi ya "kuburuta uhuishaji" kwenye skrini ya kugusa. Huenda kukawa na hesabu za sehemu zinazoelea kidogo sana katika vizuizi vya kusonga, na hii inategemea mfano maalum.

Wazo la ufanisi zaidi lilikuwa kuhamisha fremu kutoka SDRAM hadi kwenye kumbukumbu ya ndani. Ili kufanya hivyo, tulifanya vipimo vya skrini sio 480x272, lakini 272x272. Pia tulipunguza kina cha rangi kutoka A8R8G8B8 hadi R5G6B5, na hivyo kupunguza ukubwa wa pikseli moja kutoka baiti 4 hadi 2. Ukubwa wa framebuffer unaotokana ni 272 * 272 * 2 = 147968 byte. Hii ilitoa kasi kubwa, labda dhahiri zaidi, uhuishaji ukawa karibu laini.

Uboreshaji wa hivi punde ulikuwa ni kutumia msimbo wa Embox kutoka RAM na msimbo wa Qt kutoka SDRAM. Ili kufanya hivyo, sisi kwanza, kama kawaida, tunaunganisha Embox pamoja na Qt, lakini tunaweka maandishi, rodata, data na sehemu za bss za maktaba katika QSPI ili kisha kunakili kwa 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))

Kwa kutekeleza msimbo wa Embox kutoka ROM, tulipokea pia kasi inayoonekana. Kama matokeo, uhuishaji uligeuka kuwa laini kabisa:


Mwishowe, wakati wa kuandaa kifungu na kujaribu usanidi tofauti wa Embox, ilibainika kuwa vizuizi vya kusonga vya Qt hufanya kazi vizuri kutoka kwa QSPI na kiunzi cha fremu katika SDRAM, na kizuizi kilikuwa sawa na saizi ya fremu! Inaonekana, ili kuondokana na "onyesho la slaidi" la awali, kuongeza kasi ya mara 2 ilikuwa ya kutosha kutokana na kupunguzwa kwa banal kwa ukubwa wa framebuffer. Lakini haikuwezekana kufikia matokeo kama haya kwa kuhamisha nambari ya Embox tu kwa kumbukumbu anuwai za haraka (kuongeza kasi haikuwa 2, lakini karibu mara 1.5).

Jinsi ya kujaribu mwenyewe

Ikiwa una STM32F7-Discovery, unaweza kuendesha Qt chini ya Embox mwenyewe. Unaweza kusoma jinsi hii inafanywa kwenye yetu wiki.

Hitimisho

Kama matokeo, tuliweza kuzindua Qt! Ugumu wa kazi, kwa maoni yetu, umezidishwa. Kwa kawaida, unahitaji kuzingatia maalum ya microcontrollers na kwa ujumla kuelewa usanifu wa mifumo ya kompyuta. Matokeo ya uboreshaji yanaelekeza kwenye ukweli unaojulikana kuwa kizuizi katika mfumo wa kompyuta sio kichakataji, lakini kumbukumbu.

Mwaka huu tutashiriki katika tamasha TechTrain. Hapo tutakuambia kwa undani zaidi na kuonyesha Qt, OpenCV kwenye vidhibiti vidogo na mafanikio yetu mengine.

Chanzo: mapenzi.com

Kuongeza maoni