Porting Qt ke STM32

Selamat siang Kami dalam proyek Embox meluncurkan Qt pada STM32F7-Discovery dan ingin mengetahuinya. Sebelumnya, kami sudah memberi tahu bagaimana kami berhasil meluncurkan OpenCV .

Qt adalah kerangka kerja lintas-platform yang tidak hanya mencakup komponen grafis, tetapi juga hal-hal seperti QtNetwork, sekumpulan kelas untuk bekerja dengan database, Qt untuk Otomasi (termasuk penerapan IoT), dan banyak lagi. Pengembang tim Qt telah meramalkan penggunaan Qt dalam embedded system, sehingga pustaka-pustaka tersebut terkonfigurasi dengan cukup baik. Namun, hingga saat ini, beberapa orang berpikir untuk mengirim Qt ke mikrokontroler, mungkin karena tugas ini terlihat rumit - Qt besar, MCU kecil.

Di sisi lain, saat ini ada mikrokontroler yang dirancang untuk bekerja dengan multimedia dan lebih unggul dari Pentium pertama. Sekitar setahun yang lalu, sebuah posting muncul di blog Qt. Pengembang membuat port Qt di bawah RTEMS, dan meluncurkan contoh dengan widget di beberapa papan yang menjalankan stm32f7. Itu membuat kami tertarik. Itu terlihat, dan pengembang sendiri menulis tentang ini bahwa Qt memperlambat STM32F7-Discovery. Kami bertanya-tanya apakah kami dapat menjalankan Qt di bawah Embox, dan tidak hanya menggambar widget, tetapi memulai animasinya.

Embt telah porting Qt 4.8 untuk waktu yang lama, jadi kami memutuskan untuk mencobanya. Kami memilih aplikasi moveblocks - contoh animasi kenyal.

Kunci gerak Qt pada QEMU


Untuk memulai, kami mengkonfigurasi Qt, jika mungkin, dengan set komponen minimum yang diperlukan untuk mendukung animasi. Untuk ini ada opsi "-qconfig minimal, kecil, sedang ...". Ini termasuk file konfigurasi dari Qt dengan banyak makro - apa yang harus diaktifkan / dinonaktifkan. Setelah opsi ini, tambahkan flag lain ke konfigurasi jika kita ingin menonaktifkan yang lain. Ini adalah contoh konfigurasi kami.

Agar Qt berfungsi, Anda perlu menambahkan lapisan kompatibilitas OS. Salah satu caranya adalah dengan mengimplementasikan QPA (Qt Platform Abstraction). Dasarnya adalah plugin fb_base siap pakai sebagai bagian dari Qt, atas dasar mana QPA untuk Linux bekerja. Hasilnya adalah plugin emboxfb kecil yang menyediakan framebuffer Embox Qt, dan kemudian menggambar di sana tanpa bantuan.

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


Dan di sini gambarnya akan terlihat
 QRegion QEmboxFbScreen::doRedraw() { QVector<QRect> rects; QRegion touched = QFbScreen::doRedraw(); DPRINTF("QEmboxFbScreen::doRedraw\n"); 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 optimasi yang disertakan dari kompiler untuk ukuran memori -Os, gambar perpustakaan ternyata menjadi 3,5 MB, yang tentu saja tidak cocok dengan memori utama STM32F746. Seperti yang sudah kami tulis di artikel kami yang lain tentang OpenCV, forum ini memiliki:

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

Karena dukungan untuk mengeksekusi kode dari QSPI telah ditambahkan untuk OpenCV, kami memutuskan untuk memulai dengan memuat seluruh gambar Qtox c Embox ke dalam QSPI. Dan hore, semuanya hampir segera dimulai dari QSPI! Tetapi seperti halnya OpenCV, ternyata terlalu lambat.



Oleh karena itu, kami memutuskan untuk melakukan ini - pertama-tama salin gambar ke QSPI, kemudian muat ke SDRAM dan jalankan dari sana. Dari SDRAM sedikit lebih cepat, tetapi masih jauh dari QEMU.



Berikutnya adalah ide untuk memasukkan floating point - karena Qt melakukan beberapa perhitungan koordinat kotak dalam animasi. Mereka mencobanya, tetapi mereka tidak mendapatkan akselerasi yang terlihat, meskipun pengembang Qt mengklaim dalam artikel bahwa FPU memberikan peningkatan signifikan dalam kecepatan untuk "menyeret animasi" pada layar sentuh. Mungkin kunci gerak memiliki perhitungan floating point yang jauh lebih sedikit, dan ini tergantung pada contoh spesifik.

Ide yang paling efektif adalah mentransfer framebuffer dari SDRAM ke memori internal. Untuk ini, kami tidak memiliki ukuran layar 480x272, tetapi 272x272. Kami juga mengurangi kedalaman warna dari A8R8G8B8 ke R5G6B5, sehingga mengurangi ukuran satu piksel dari 4 menjadi 2 byte. Kami mendapat ukuran framebuffer 272 * 272 * 2 = 147968 byte. Ini memberi akselerasi yang signifikan, mungkin yang paling mencolok, animasinya menjadi hampir mulus.

Optimasi terakhir adalah eksekusi kode Embox dari RAM, dan Qt dari SDRAM. Untuk melakukan ini, kita pertama-tama, seperti biasa, menghubungkan Embox secara statis bersama dengan Qt, tetapi kami menempatkan segmen teks, rodata, data, dan pustaka bss di QSPI, sehingga nanti kami dapat 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)) 

Karena eksekusi kode, Embox dari ROM juga menerima akselerasi nyata. Hasilnya, animasi ternyata cukup lancar:


Sudah di bagian paling akhir, saat menyiapkan artikel dan mencoba berbagai konfigurasi Embox, ternyata Qt moveblocks berfungsi dengan baik dari QSPI dengan framebuffer di SDRAM, dan ukuran framebuffer adalah hambatan! Rupanya, untuk mengatasi "slideshow" awal, akselerasi 2 kali sudah cukup karena pengurangan dangkal ukuran framebuffer. Tetapi itu tidak mungkin untuk mencapai hasil seperti itu dengan hanya mentransfer kode Embox ke berbagai memori cepat (akselerasi diperoleh bukan oleh 2, tetapi sekitar 1,5 kali).

Cara mencobanya sendiri


Jika Anda memiliki STM32F7-Discovery, Anda dapat menjalankan Qt di bawah Embox sendiri. Anda dapat membaca bagaimana melakukan ini di wiki kami.

Kesimpulan


Sebagai hasilnya, kami berhasil meluncurkan Qt! Kompleksitas tugas, menurut pendapat kami, agak berlebihan. Secara alami, Anda perlu mempertimbangkan secara spesifik mikrokontroler dan secara umum memahami arsitektur sistem komputasi. Hasil optimasi menunjukkan fakta yang terkenal bahwa hambatan dalam sistem komputasi bukan prosesor, tetapi memori.

Tahun ini kami akan berpartisipasi dalam festival TechTrain . Di sana kami akan memberi tahu lebih detail dan menunjukkan Qt, OpenCV pada mikrokontroler dan pencapaian kami lainnya.

Source: https://habr.com/ru/post/id459730/


All Articles