Qt-ի տեղափոխում STM32-ին

Qt-ի տեղափոխում STM32-ինԲարի օր Մենք նախագծում ենք Embox գործարկել է Qt-ը STM32F7-Discovery-ում և կցանկանայի խոսել դրա մասին: Ավելի վաղ մենք արդեն պատմել էինք, թե ինչպես կարողացանք գործարկել Opencv.

Qt-ը միջպլատֆորմային շրջանակ է, որը ներառում է ոչ միայն գրաֆիկական բաղադրիչներ, այլ նաև այնպիսի բաներ, ինչպիսիք են QtNetwork-ը, տվյալների բազաների հետ աշխատելու համար նախատեսված դասերի հավաքածու, Qt ավտոմատացման համար (ներառյալ IoT ներդրման համար) և շատ ավելին: Qt թիմը ակտիվ է եղել Qt-ն ներկառուցված համակարգերում օգտագործելու հարցում, ուստի գրադարանները բավականին կարգավորելի են: Այնուամենայնիվ, մինչև վերջերս քչերն էին մտածում Qt-ը միկրոկարգավորիչներ տեղափոխելու մասին, հավանաբար այն պատճառով, որ նման առաջադրանքը դժվար է թվում. Qt-ը մեծ է, MCU-ները փոքր են:

Մյուս կողմից, այս պահին կան միկրոկոնտրոլերներ, որոնք նախատեսված են մուլտիմեդիայի հետ աշխատելու համար և գերազանցում են առաջին Pentium-ներին: Մոտ մեկ տարի առաջ հայտնվեց Qt բլոգը գրառում. Մշակողները ստեղծել են Qt մի նավահանգիստ RTEMS OS-ի համար և գործարկել են վիդջեթների օրինակներ մի քանի տախտակների վրա, որոնք աշխատում են stm32f7: Սա մեզ հետաքրքրեց։ Նկատելի էր, և մշակողները իրենք են գրում այդ մասին, որ Qt-ը դանդաղ է STM32F7-Discovery-ի վրա։ Մենք մտածում էինք՝ կարո՞ղ ենք Qt-ն գործարկել Embox-ի տակ և ոչ միայն վիջեթ նկարել, այլ գործարկել անիմացիա:

Qt 4.8-ը երկար ժամանակ տեղափոխված է Embox-ում, ուստի մենք որոշեցինք փորձել այն դրա վրա: Մենք ընտրեցինք moveblocks հավելվածը՝ զսպանակավոր անիմացիայի օրինակ։

Qt-ը շարժվում է QEMU-ումQt-ի տեղափոխում STM32-ին

Սկզբից մենք կարգավորում ենք Qt-ը, հնարավորության դեպքում, անիմացիան աջակցելու համար անհրաժեշտ բաղադրիչների նվազագույն փաթեթով: Դրա համար կա «-qconfig նվազագույն, փոքր, միջին...» տարբերակ: Այն միացնում է Qt-ից կազմաձևման ֆայլը բազմաթիվ մակրոների հետ՝ ինչ միացնել/ինչ անջատել: Այս տարբերակից հետո մենք այլ դրոշակներ ենք ավելացնում կոնֆիգուրացիայի մեջ, եթե ցանկանում ենք այլ բան անջատել: Ահա մեր օրինակը կոնֆիգուրացիա.

Որպեսզի Qt-ն աշխատի, դուք պետք է ավելացնեք ՕՀ-ի համատեղելիության շերտ: Ճանապարհներից մեկը QPA-ի (Qt Platform Abstraction) ներդրումն է: Մենք հիմք ենք ընդունել Qt-ում ներառված պատրաստի fb_base փլագինը, որի հիման վրա աշխատում է QPA-ն Linux-ի համար։ Արդյունքը փոքր փլագին է, որը կոչվում է emboxfb, որը Qt-ին տրամադրում է Embox-ի շրջանակային բուֆեր, այնուհետև այն նկարում է այնտեղ՝ առանց որևէ արտաքին օգնության:

Ահա թե ինչ տեսք ունի 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 (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();
}

Եվ ահա թե ինչ տեսք կունենա վերագծագրումը

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

Արդյունքում, երբ միացված է հիշողության չափի համար կոմպիլյատորների օպտիմալացում -Os, գրադարանի պատկերը ստացվեց 3.5 ՄԲ, ինչը, իհարկե, չի տեղավորվում STM32F746-ի հիմնական հիշողության մեջ: Ինչպես արդեն գրել ենք OpenCV-ի մասին մեր մյուս հոդվածում, այս տախտակն ունի.

  • 1 ՄԲ ROM
  • 320 KB RAM
  • 8 ՄԲ SDRAM
  • 16 ՄԲ QSPI

Քանի որ QSPI-ից կոդի կատարման աջակցությունն արդեն ավելացվել է OpenCV-ին, մենք որոշեցինք սկսել՝ բեռնելով ողջ Embox c Qt պատկերը QSPI-ում: Եվ արագ, ամեն ինչ սկսվեց գրեթե անմիջապես QSPI-ից: Բայց ինչպես OpenCV-ի դեպքում, այնպես էլ պարզվեց, որ այն չափազանց դանդաղ է աշխատում։

Qt-ի տեղափոխում STM32-ին

Հետևաբար, մենք որոշեցինք դա անել այսպես. նախ պատճենում ենք պատկերը QSPI-ում, այնուհետև բեռնում ենք այն SDRAM-ում և կատարում այնտեղից: SDRAM-ից այն դարձավ մի փոքր ավելի արագ, բայց դեռ հեռու է QEMU-ից:

Qt-ի տեղափոխում STM32-ին

Այնուհետև միտք եղավ ներառել լողացող կետ. ի վերջո, Qt-ն անում է անիմացիայի մեջ քառակուսիների կոորդինատների որոշ հաշվարկներ: Փորձեցինք, բայց այստեղ տեսանելի արագացում չստացանք, թեև ներս Հոդված Qt-ի մշակողները պնդում էին, որ FPU-ն արագության զգալի աճ է տալիս սենսորային էկրանով «անիմացիան քաշելու» համար: Շարժվող բլոկներում կարող են զգալիորեն ավելի քիչ լինել լողացող կետի հաշվարկները, և դա կախված է կոնկրետ օրինակից:

Ամենաարդյունավետ գաղափարը Framebuffer-ը SDRAM-ից ներքին հիշողություն տեղափոխելն էր: Դա անելու համար մենք էկրանի չափերը դարձրեցինք ոչ թե 480x272, այլ 272x272: Մենք նաև իջեցրեցինք գույնի խորությունը A8R8G8B8-ից մինչև R5G6B5՝ այդպիսով մեկ պիքսելի չափը 4-ից նվազեցնելով 2 բայթի: Ստացված շրջանակի բուֆերի չափը 272 * 272 * 2 = 147968 բայթ է: Սա զգալի արագացում տվեց, թերևս առավել նկատելի էր, որ անիմացիան գրեթե հարթ դարձավ:

Վերջին օպտիմիզացումը եղել է Embox կոդը RAM-ից, իսկ Qt կոդը SDRAM-ից գործարկելը: Դա անելու համար մենք նախ, ինչպես միշտ, ստատիկ կերպով կապում ենք Embox-ը Qt-ի հետ, բայց գրադարանի տեքստը, rodata-ն, տվյալները և bss հատվածները տեղադրում ենք QSPI-ում, որպեսզի այն պատճենենք այն 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))

ROM-ից Embox կոդը գործարկելով՝ մենք նաև նկատելի արագացում ստացանք։ Արդյունքում անիմացիան բավականին հարթ ստացվեց.


Հենց վերջում, հոդվածը պատրաստելիս և Embox-ի տարբեր կոնֆիգուրացիաներ փորձելիս, պարզվեց, որ Qt moveblocks-ը հիանալի է աշխատում QSPI-ից՝ SDRAM-ի շրջանակային բուֆերով, և շեղը հենց շրջանակի չափն էր: Ըստ երևույթին, նախնական «սլայդշոուն» հաղթահարելու համար բավարար էր 2 անգամ արագացումը՝ շրջանակային բուֆերի չափի սովորական նվազման պատճառով: Բայց միայն Embox կոդը տարբեր արագ հիշողություններ փոխանցելով (արագացումը ոչ թե 2, այլ մոտ 1.5 անգամ էր) հնարավոր չէր հասնել նման արդյունքի։

Ինչպես փորձել ինքներդ

Եթե ​​դուք ունեք STM32F7-Discovery, կարող եք ինքներդ գործարկել Qt-ը Embox-ի տակ: Դուք կարող եք կարդալ, թե ինչպես է դա արվում մեր կայքում վիքի.

Ամփոփում

Արդյունքում մեզ հաջողվեց գործարկել Qt! Առաջադրանքի բարդությունը, մեր կարծիքով, որոշ չափով չափազանցված է։ Բնականաբար, դուք պետք է հաշվի առնեք միկրոկոնտրոլերների առանձնահատկությունները և ընդհանուր առմամբ հասկանաք համակարգչային համակարգերի ճարտարապետությունը: Օպտիմալացման արդյունքները մատնանշում են այն հայտնի փաստը, որ հաշվողական համակարգի խոչընդոտը ոչ թե պրոցեսորն է, այլ հիշողությունը:

Այս տարի մենք մասնակցելու ենք փառատոնին TechTrain. Այնտեղ մենք ձեզ ավելի մանրամասն կպատմենք և ցույց կտանք Qt, OpenCV միկրոկոնտրոլերների վրա և մեր մյուս ձեռքբերումները։

Source: www.habr.com

Добавить комментарий