Qt-ті STM32-ге тасымалдау

Qt-ті STM32-ге тасымалдауҚайырлы күн! Біз жобадамыз Эмбокс STM32F7-Discovery жүйесінде Qt іске қосылды және бұл туралы айтқысы келеді. Бұған дейін біз қалай іске қосқанымызды айтқан болатынбыз OpenCV.

Qt – бұл тек графикалық құрамдастарды ғана емес, сонымен қатар QtNetwork, дерекқорлармен жұмыс істеуге арналған сыныптар жиынтығы, автоматтандыруға арналған Qt (соның ішінде IoT енгізу үшін) және т.б. сияқты нәрселерді қамтитын кросс-платформалық құрылым. Qt командасы ендірілген жүйелерде Qt пайдалану туралы белсенді болды, сондықтан кітапханалар өте конфигурацияланады. Дегенмен, соңғы уақытқа дейін Qt-ті микроконтроллерлерге тасымалдау туралы аз адамдар ойлады, мүмкін, мұндай тапсырма қиын болып көрінетіндіктен - Qt үлкен, MCU кішкентай.

Екінші жағынан, қазіргі уақытта мультимедиамен жұмыс істеуге арналған және бірінші Pentiums-тен жоғары микроконтроллерлер бар. Шамамен бір жыл бұрын Qt блогы пайда болды пошта. Әзірлеушілер RTEMS ОЖ үшін Qt портын жасады және stm32f7 жұмыс істейтін бірнеше тақталарда виджеттері бар мысалдарды іске қосты. Бұл бізді қызықтырды. Бұл байқалды және әзірлеушілердің өздері бұл туралы жазады, Qt STM32F7-Discovery-де баяу. Біз Qt бағдарламасын Embox астында іске қосып, виджетті ғана емес, анимацияны іске қоса аламыз ба деп ойладық.

Qt 4.8 ұзақ уақыт бойы Embox-қа көшірілді, сондықтан біз оны қолданып көруді шештік. Біз серіппелі анимацияның мысалы ретінде moveblocks қолданбасын таңдадық.

QEMU жүйесіндегі Qt жылжыту блоктарыQt-ті STM32-ге тасымалдау

Бастау үшін Qt мүмкіндігінше анимацияны қолдау үшін қажетті құрамдастардың ең аз жиынтығымен конфигурациялаймыз. Бұл үшін «-qconfig minimal, small, media...» опциясы бар. Ол Qt конфигурация файлын көптеген макростармен қосады - не қосу керек / не өшіру керек. Осы опциядан кейін біз басқа нәрсені өшіргіміз келсе, конфигурацияға басқа жалаушаларды қосамыз. Міне, біздің мысал конфигурация.

Qt жұмыс істеуі үшін ОЖ үйлесімділік деңгейін қосу керек. Бір жолы 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 КБ жедел жады
  • 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 байт. Бұл айтарлықтай жеделдету берді, мүмкін, ең маңыздысы, анимация дерлік тегіс болды.

Соңғы оңтайландыру жедел жадтан 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 болса, Qt бағдарламасын Embox астында өзіңіз іске қоса аласыз. Бұл қалай жасалатынын біздің сайтымыздан оқи аласыз wiki.

қорытынды

Нәтижесінде біз Qt іске қостық! Тапсырманың күрделілігі, біздің ойымызша, біршама әсірелеу. Әрине, сіз микроконтроллерлердің ерекшеліктерін ескеруіңіз керек және жалпы компьютерлік жүйелердің архитектурасын түсінуіңіз керек. Оңтайландыру нәтижелері есептеу жүйесіндегі тығырық процессор емес, жад екені белгілі фактіні көрсетеді.

Биыл фестивальге қатысамыз TechTrain. Онда біз сізге толығырақ айтып береміз және микроконтроллерлерде Qt, OpenCV және басқа да жетістіктерімізді көрсетеміз.

Ақпарат көзі: www.habr.com

пікір қалдыру