Qtти STM32ге өткөрүү

Qtти STM32ге өткөрүүКутмандуу күнүң менен! Биз долбоордобуз Embox STM32F7-Discovery боюнча Qt ишке киргизди жана бул тууралуу айткым келет. Буга чейин кантип ишке киргизгенибизди айтканбыз OpenCV.

Qt – бул графикалык компоненттерди гана эмес, QtNetwork, маалымат базалары менен иштөө үчүн класстар топтому, автоматташтыруу үчүн Qt (анын ичинде IoT ишке ашыруу үчүн) жана башка көптөгөн нерселерди камтыган кайчылаш платформа. Qt командасы кыналган системаларда Qt колдонуу боюнча активдүү болду, ошондуктан китепканалар абдан конфигурацияланган. Бирок, акыркы убакка чейин Qtти микроконтроллерлерге өткөрүү жөнүндө аз адамдар ойлошкон, кыязы, мындай тапшырма кыйындай сезилет - Qt чоң, MCU кичинекей.

Башка жагынан алганда, учурда мультимедиа менен иштөө үчүн иштелип чыккан жана биринчи Pentiums жогору микроконтроллерлер бар. Болжол менен бир жыл мурун Qt блогу пайда болгон кызмат. Иштеп чыгуучулар RTEMS OS үчүн Qt портун жасап, stm32f7 менен иштеген бир нече такталарда виджеттери бар мисалдарды ишке киргизишти. Бул бизди кызыктырды. Бул байкалды жана иштеп чыгуучулар өздөрү Qt STM32F7-Discoveryде жай экенин жазышат. Биз Qtти Embox астында иштетип, виджетти эле тартпастан, анимацияны иштете алабызбы деп ойлонуп жаттык.

Qt 4.8 көптөн бери Embox'ка көчүрүлгөн, ошондуктан биз аны сынап көрүүнү чечтик. Биз Moveblocks тиркемесин тандап алдык - жазгы анимациянын мисалы.

QEMU боюнча Qt кыймыл блокторуQtти STM32ге өткөрүү

Баштоо үчүн, мүмкүн болсо, анимацияны колдоо үчүн керектүү компоненттердин минималдуу топтому менен Qt конфигурациялайбыз. Бул үчүн "-qconfig минималдуу, кичине, орто..." параметри бар. Ал Qt конфигурация файлын көптөгөн макростар менен байланыштырат - эмнени иштетүү керек / эмнени өчүрүү керек. Бул параметрден кийин, биз башка нерсени өчүргүбүз келсе, конфигурацияга башка желектерди кошобуз. Мына биздин мисал тарам.

Qt иштеши үчүн, сиз OS шайкештик катмарын кошушуңуз керек. Бир жолу QPA (Qt Platform Abstraction) ишке ашыруу болуп саналат. Биз негиз катары Qt камтылган даяр fb_base плагинин алдык, анын негизинде Linux үчүн QPA иштейт. Натыйжада Qtти Embox'тун фреймбуфери менен камсыз кылган emboxfb деп аталган кичинекей плагин, андан кийин ал эч кандай сырттан жардамсыз тартат.

Бул плагинди түзүү сыяктуу көрүнөт

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 сенсордук экранда "анимацияны сүйрөө" үчүн ылдамдыкты бир топ жогорулатат деп ырасташкан. Кыймыл блокторунда калкыма чекиттерди эсептөөлөр кыйла аз болушу мүмкүн жана бул конкреттүү мисалга жараша болот.

Эң эффективдүү идея фреймбуферди SDRAMдан ички эс тутумга жылдыруу болгон. Бул үчүн биз экрандын өлчөмдөрүн 480x272 эмес, 272x272 кылдык. Ошондой эле биз түс тереңдигин A8R8G8B8ден R5G6B5ке түшүрдүк, ошентип бир пикселдин өлчөмүн 4төн 2 байтка чейин азайттык. Натыйжадагы кадр буферинин өлчөмү 272 * 272 * 2 = 147968 байт. Бул бир кыйла тездетүүнү берди, балким эң байкаларлык, анимация дээрлик жылмакай болуп калды.

Акыркы оптималдаштыруу RAMдан Embox кодун жана SDRAMдан Qt кодун иштетүү болду. Бул үчүн, биз адегенде, адаттагыдай эле, Embox менен Qt менен статикалык байланыштырабыз, бирок SDRAMга көчүрүү үчүн китепкананын текстин, родаталарын, берилиштерин жана bss сегменттерин QSPIге жайгаштырабыз.

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 бар болсо, сиз Embox астында Qt иштете аласыз. Бул кантип жасалганын биздин баракчадан окуй аласыз wiki.

жыйынтыктоо

Натыйжада биз Qt! Милдеттин татаалдыгы, биздин оюбузча, бир аз апыртылган. Албетте, сиз микроконтроллерлердин өзгөчөлүктөрүн эске алып, компьютердик системалардын архитектурасын жалпысынан түшүнүшүңүз керек. Оптималдаштыруунун натыйжалары эсептөө тутумундагы кыйынчылык процессор эмес, эстутум экендиги белгилүү чындыкты көрсөтүп турат.

Быйыл фестивалга катышабыз TechTrain. Ал жерде биз сизге кененирээк айтып беребиз жана микроконтроллерлерде Qt, OpenCV жана башка жетишкендиктерибизди көрсөтөбүз.

Source: www.habr.com

Комментарий кошуу