Memindahkan Qt ke STM32

Memindahkan Qt ke STM32Selamat petang Kami berada dalam projek itu Embox melancarkan Qt pada STM32F7-Discovery dan ingin membincangkannya. Sebelum ini, kami sudah memberitahu bagaimana kami berjaya melancarkan OpenCV.

Qt ialah rangka kerja merentas platform yang merangkumi bukan sahaja komponen grafik, tetapi juga perkara seperti QtNetwork, satu set kelas untuk bekerja dengan pangkalan data, Qt untuk Automasi (termasuk untuk pelaksanaan IoT) dan banyak lagi. Pasukan Qt telah proaktif menggunakan Qt dalam sistem terbenam, jadi perpustakaan agak boleh dikonfigurasikan. Walau bagaimanapun, sehingga baru-baru ini, beberapa orang berfikir tentang mengalihkan Qt ke mikropengawal, mungkin kerana tugas sedemikian kelihatan sukar - Qt besar, MCU kecil.

Sebaliknya, pada masa ini terdapat mikropengawal yang direka untuk berfungsi dengan multimedia dan lebih baik daripada Pentium pertama. Kira-kira setahun yang lalu, blog Qt muncul jawatan. Pembangun membuat port Qt untuk OS RTEMS, dan melancarkan contoh dengan widget pada beberapa papan yang menjalankan stm32f7. Ini menarik minat kami. Ia adalah ketara, dan pembangun sendiri menulis mengenainya, bahawa Qt lambat pada STM32F7-Discovery. Kami tertanya-tanya sama ada kami boleh menjalankan Qt di bawah Embox, dan bukan hanya melukis widget, tetapi menjalankan animasi.

Qt 4.8 telah dialihkan ke Embox untuk masa yang lama, jadi kami memutuskan untuk mencubanya. Kami memilih aplikasi moveblocks - contoh animasi kenyal.

Qt moveblocks pada QEMUMemindahkan Qt ke STM32

Sebagai permulaan, kami mengkonfigurasi Qt, jika boleh, dengan set komponen minimum yang diperlukan untuk menyokong animasi. Untuk ini terdapat pilihan "-qconfig minimal, kecil, sederhana...". Ia menghubungkan fail konfigurasi daripada Qt dengan banyak makro - apa yang perlu didayakan / apa yang perlu dilumpuhkan. Selepas pilihan ini, kami menambah bendera lain pada konfigurasi jika kami mahu melumpuhkan sesuatu yang lain. Berikut adalah contoh kami konfigurasi.

Untuk membolehkan Qt berfungsi, anda perlu menambah lapisan keserasian OS. Salah satu cara adalah dengan melaksanakan QPA (Qt Platform Abstraction). Kami mengambil sebagai asas pemalam fb_base siap sedia disertakan dalam Qt, berdasarkan QPA untuk Linux yang berfungsi. Hasilnya ialah pemalam kecil yang dipanggil emboxfb, yang menyediakan Qt dengan framebuffer Embox, dan kemudian ia melukis ke sana tanpa sebarang bantuan luar.

Beginilah rupa membuat pemalam

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

Dan inilah rupa lukisan semula itu

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

Akibatnya, dengan pengoptimuman pengkompil untuk saiz memori -Os didayakan, imej perpustakaan ternyata menjadi 3.5 MB, yang sudah tentu tidak sesuai dengan memori utama STM32F746. Seperti yang telah kami tulis dalam artikel kami yang lain tentang OpenCV, papan ini mempunyai:

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

Memandangkan sokongan untuk melaksanakan kod daripada QSPI telah ditambahkan pada OpenCV, kami memutuskan untuk bermula dengan memuatkan keseluruhan imej Embox c Qt ke dalam QSPI. Dan hore, semuanya bermula dengan serta-merta dari QSPI! Tetapi seperti dalam kes OpenCV, ternyata ia berfungsi terlalu perlahan.

Memindahkan Qt ke STM32

Oleh itu, kami memutuskan untuk melakukannya dengan cara ini - mula-mula kami menyalin imej ke QSPI, kemudian memuatkannya ke SDRAM dan melaksanakan dari sana. Dari SDRAM ia menjadi lebih pantas sedikit, tetapi masih jauh dari QEMU.

Memindahkan Qt ke STM32

Seterusnya, terdapat idea untuk memasukkan titik terapung - lagipun, Qt melakukan beberapa pengiraan koordinat petak dalam animasi. Kami mencuba, tetapi di sini kami tidak mendapat apa-apa pecutan yang kelihatan, walaupun dalam artikel Pemaju Qt mendakwa bahawa FPU memberikan peningkatan yang ketara dalam kelajuan untuk "menyeret animasi" pada skrin sentuh. Mungkin terdapat kurang pengiraan titik terapung dengan ketara dalam sekatan bergerak, dan ini bergantung pada contoh khusus.

Idea yang paling berkesan adalah untuk memindahkan framebuffer dari SDRAM ke memori dalaman. Untuk melakukan ini, kami membuat dimensi skrin bukan 480x272, tetapi 272x272. Kami juga menurunkan kedalaman warna daripada A8R8G8B8 kepada R5G6B5, sekali gus mengurangkan saiz satu piksel daripada 4 kepada 2 bait. Saiz framebuffer yang terhasil ialah 272 * 272 * 2 = 147968 bait. Ini memberikan pecutan yang ketara, mungkin yang paling ketara, animasi menjadi hampir lancar.

Pengoptimuman terkini adalah untuk menjalankan kod Embox daripada RAM dan kod Qt daripada SDRAM. Untuk melakukan ini, kami mula-mula, seperti biasa, memautkan Embox secara statik bersama-sama dengan Qt, tetapi kami meletakkan segmen teks, rodata, data dan bss perpustakaan dalam QSPI untuk kemudian menyalinnya ke 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))

Dengan melaksanakan kod Embox daripada ROM, kami juga menerima pecutan yang ketara. Akibatnya, animasi ternyata agak lancar:


Pada penghujungnya, semasa menyediakan artikel dan mencuba konfigurasi Embox yang berbeza, ternyata Qt moveblocks berfungsi dengan baik daripada QSPI dengan framebuffer dalam SDRAM, dan bottleneck adalah tepat sebesar framebuffer! Nampaknya, untuk mengatasi "tayangan slaid" awal, pecutan 2 kali ganda sudah mencukupi kerana pengurangan cetek dalam saiz framebuffer. Tetapi tidak mungkin untuk mencapai hasil sedemikian dengan memindahkan hanya kod Embox ke pelbagai kenangan pantas (pecutan bukan 2, tetapi kira-kira 1.5 kali).

Macam mana nak cuba sendiri

Jika anda mempunyai STM32F7-Discovery, anda boleh menjalankan Qt di bawah Embox sendiri. Anda boleh membaca cara ini dilakukan di laman web kami wiki.

Kesimpulan

Hasilnya, kami berjaya melancarkan Qt! Kerumitan tugas, pada pendapat kami, agak dibesar-besarkan. Sememangnya, anda perlu mengambil kira spesifikasi mikropengawal dan secara amnya memahami seni bina sistem komputer. Keputusan pengoptimuman menunjukkan fakta yang terkenal bahawa kesesakan dalam sistem pengkomputeran bukanlah pemproses, tetapi memori.

Tahun ini kami akan menyertai festival tersebut TechTrain. Di sana kami akan memberitahu anda dengan lebih terperinci dan menunjukkan Qt, OpenCV pada mikropengawal dan pencapaian kami yang lain.

Sumber: www.habr.com

Tambah komen