Qt-г STM32 руу шилжүүлэх

Qt-г STM32 руу шилжүүлэхӨдрийн мэнд Бид төсөлд хамрагдаж байна Embox 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-д удаан хугацаагаар суулгагдсан тул бид үүнийг туршиж үзэхээр шийдсэн. Бид хөдөлгөөнт блокуудын програмыг сонгосон - хаврын хөдөлгөөнт дүрсний жишээ.

QEMU дээрх Qt хөдөлгөөнт блокуудQt-г STM32 руу шилжүүлэх

Эхлээд бид Qt-г боломжтой бол хөдөлгөөнт дүрсийг дэмжихэд шаардагдах хамгийн бага бүрэлдэхүүн хэсгүүдээр тохируулдаг. Үүний тулд "-qconfig minimal,small,medium..." гэсэн сонголт байдаг. Энэ нь Qt-аас тохиргооны файлыг олон макротой холбодог - юуг идэвхжүүлэх / юуг идэвхгүй болгох. Энэ тохируулгын дараа бид өөр зүйлийг идэвхгүй болгохыг хүсвэл тохиргоонд бусад тугуудыг нэмнэ. Бидний жишээ энд байна тохиргоо.

Qt ажиллахын тулд та үйлдлийн системийн нийцтэй давхаргыг нэмэх хэрэгтэй. Нэг арга зам бол QPA (Qt Platform Abstraction) хэрэгжүүлэх явдал юм. Бид Qt-д багтсан бэлэн fb_base залгаасыг үндэс болгон авсан бөгөөд үүний үндсэн дээр Linux-д зориулсан QPA ажилладаг. Үүний үр дүнд 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 MB болсон нь мэдээж STM32F746-ийн үндсэн санах ойд тохирохгүй байна. OpenCV-ийн тухай өөр нийтлэлдээ бид аль хэдийн бичсэнчлэн энэ самбар нь:

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

OpenCV-д QSPI-ийн кодыг гүйцэтгэх дэмжлэг аль хэдийн нэмэгдсэн тул бид 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-тэй статик байдлаар холбодог боловч номын сангийн текст, өгөгдөл, өгөгдөл, 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 байгаа бол та өөрөө Embox дор Qt-г ажиллуулж болно. Үүнийг хэрхэн яаж хийхийг та манай вэбсайтаас уншиж болно вики.

дүгнэлт

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

Энэ жил бид наадамд оролцоно TechTrain. Тэнд бид танд илүү дэлгэрэнгүй ярьж, Qt, OpenCV дээр микроконтроллерууд болон бусад амжилтуудыг харуулах болно.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх