Hayrli kun! Biz loyihadamiz. Biz Qt-ni STM32F7-Discovery-da ishga tushirdik va tajribamiz bilan o'rtoqlashmoqchimiz. Biz uni qanday yo‘lga qo‘yganimiz haqida avvalroq o‘rtoqlashdik. .
Qt - bu nafaqat grafik komponentlarni, balki QtNetwork kabi xususiyatlarni, ma'lumotlar bazalari bilan ishlash uchun sinflar to'plamini, avtomatlashtirish uchun Qt (jumladan, IoTni amalga oshirish uchun) va boshqa ko'p narsalarni o'z ichiga olgan o'zaro faoliyat platforma. Qt jamoasining ishlab chiquvchilari Qt ning o'rnatilgan tizimlarda ishlatilishini kutishgan, shuning uchun kutubxonalar juda sozlanishi mumkin. Biroq, yaqin vaqtgacha kamdan-kam odamlar Qt ni mikrokontrollerlarga o'tkazish haqida o'ylashgan, ehtimol bu vazifa qo'rqinchli tuyulganligi sababli - Qt katta, MCU esa kichik.
Boshqa tomondan, hozirda multimediya uchun mo'ljallangan mikrokontrollerlar mavjud bo'lib, ular birinchi Pentiumlardan ustun turadi. Taxminan bir yil oldin Qt blogida post paydo bo'ldi Ishlab chiquvchilar Qt-ni RTEMS OS-ga ko'chirishdi va STM32F7 bilan ishlaydigan bir nechta platalarda vidjet misollarini ishga tushirishdi. Bu bizning qiziqishimizni uyg'otdi. Bu sezilarli edi va ishlab chiquvchilarning o'zlari Qt STM32F7-Discovery-da sekin bo'lganligi haqida xabar berishgan. Biz Qt-ni Embox-da ishga tushirib, nafaqat vidjetlarni chizish, balki animatsiyalarni ham ishga tushirishimiz mumkinmi, deb hayron bo'ldik.
Embox allaqachon Qt 4.8 ni o'tkazgan edi, shuning uchun biz uni sinab ko'rishga qaror qildik. Biz harakat bloklari ilovasini tanladik - bunyodkor animatsiya namunasi.
QEMU-da Qt ko'chirish bloklari
Boshlash uchun Qt-ni animatsiyani qo'llab-quvvatlash uchun zarur bo'lgan minimal mumkin bo'lgan komponentlar to'plami bilan sozlang. Buning uchun "-qconfig minimal, kichik, o'rta..." variantidan foydalaning. U Qt-ga kiritilgan konfiguratsiya faylini o'z ichiga oladi, bir qator makrolar - nimani yoqish/o'chirish. Ushbu parametrdan so'ng, agar biror narsani o'chirib qo'ymoqchi bo'lsangiz, konfiguratsiyaga boshqa bayroqlarni qo'shing. Mana bizning misolimiz. .
Qt ishlashi uchun biz OS moslik qatlamini qo'shishimiz kerak. Buning bir usuli QPA (Qt Platform Abstraction) ni amalga oshirishdir. Biz Qt bilan birga mavjud fb_base plaginidan foydalandik, u Linux uchun QPA-ni quvvatlantiradi. Natijada emboxfb deb nomlangan kichik plagin paydo bo'ldi, u Qt-ni Embox-ning ramka buferi bilan ta'minlaydi va keyin unga hech qanday yordamsiz jalb qiladi.
Plaginni yaratish shunday ko'rinadi
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();
}
Va qayta chizish shunday ko'rinadi
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 kompilyator xotirasini optimallashtirish yoqilgan bo'lsa, kutubxona tasviri 3.5 MB ni tashkil etdi, bu STM32F746 asosiy xotirasiga to'g'ri kelmasligi aniq. OpenCV haqidagi boshqa maqolamizda aytib o'tganimizdek, ushbu kengashda quyidagilar mavjud:
- 1 MB ROM
- 320 KB operativ xotira
- 8 MB SDRAM
- 16 MB QSPI
OpenCV allaqachon QSPI kodini bajarishni qo'llab-quvvatlaganligi sababli, biz butun Embox Qt tasvirini QSPI-ga yuklashdan boshlashga qaror qildik. Va afsuski, hamma narsa QSPI dan deyarli darhol yugurdi! Ammo OpenCV-da bo'lgani kabi, u juda sekin bo'lib chiqdi.

Shunday qilib, biz buni shunday qilishga qaror qildik: avval tasvirni QSPI-ga nusxalash, keyin uni SDRAM-ga yuklash va u yerdan ishga tushirish. SDRAM dan biroz tezroq bo'ldi, lekin baribir QEMU dan ancha orqada.

Keyinchalik suzuvchi nuqtani yoqish g'oyasi paydo bo'ldi, chunki Qt animatsiyada kvadrat koordinatalarini hisoblashning bir qismini bajaradi. Biz buni sinab ko'rdik, ammo sezilarli tezlikni ko'rmadik Qt ishlab chiquvchilari ta'kidlashicha, FPU sensorli ekranlarda "animatsiyalarni sudrab borish" uchun sezilarli tezlikni oshiradi. Harakatlanuvchi bloklar suzuvchi nuqtali hisoblarni sezilarli darajada kamroq ishlatishi mumkin va bu aniq misolga bog'liq.
Eng samarali g'oya freymbuferni SDRAMdan ichki xotiraga ko'chirish bo'lib chiqdi. Bunga erishish uchun biz ekran o'lchamini 480x272 dan 272x272 ga o'zgartirdik. Shuningdek, biz rang chuqurligini A8R8G8B8 dan R5G6B5 ga tushirdik va shu bilan piksel hajmini 4 baytdan 2 baytgacha kamaytirdik. Natijada 272 * 272 * 2 = 147968 bayt hajmdagi ramka buferi paydo bo'ldi. Bu sezilarli tezlikka olib keldi, ehtimol eng sezilarli: animatsiya deyarli silliq bo'ldi.
Yakuniy optimallashtirish RAMdan Embox kodini va SDRAMdan Qtni bajarish edi. Bunga erishish uchun biz avval odatdagidek Embox va Qt ni statik ravishda bog‘laymiz, lekin kutubxona matni, ma’lumotlari, ma’lumotlari va bss segmentlarini QSPI-ga joylashtiramiz, shunda ular keyinchalik SDRAM-ga ko‘chiriladi.
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))
ROMdan Embox kodini ishga tushirish orqali biz sezilarli tezlikka erishdik. Natijada, animatsiya juda silliq bo'lib chiqdi:

Oxir-oqibat, maqolani tayyorlash va turli Embox konfiguratsiyalarini sinab ko'rish paytida, Qt moveblocks hatto SDRAM ramka buferi bilan QSPI-dan ham juda yaxshi ishlashi ma'lum bo'ldi va darboğaz aniq ramka buferining hajmi edi! Ko'rinishidan, freymbufer hajmini qisqartirish orqali 2 baravar tezlashtirish dastlabki "slayd-shou" ni engish uchun etarli edi. Biroq, bu natijaga faqat Embox kodini turli xil tezkor xotira qurilmalariga ko'chirish orqali erishib bo'lmaydi (tezlik 2x emas, balki taxminan 1.5x edi).
Qanday qilib o'zingiz sinab ko'rishingiz mumkin
Agar sizda STM32F7-Discovery bo'lsa, Qt-ni Embox-da o'zingiz ishga tushirishingiz mumkin. Buni qanday qilishni bizning veb-saytimizda o'qishingiz mumkin. .
xulosa
Nihoyat, biz Qt ni ishga tushirdik! Vazifaning murakkabligi, bizning fikrimizcha, biroz bo'rttirilgan. Tabiiyki, mikrokontrollerlarning o'ziga xos xususiyatlarini hisobga olish va umuman hisoblash tizimlarining arxitekturasini tushunish kerak. Optimallashtirish natijalari shuni ko'rsatadiki, hisoblash tizimidagi muammo protsessor emas, balki xotiradir.
Bu yil biz festivalda qatnashamiz U erda biz mikrokontrollerlarda Qt, OpenCV va boshqa yutuqlarimizni batafsil muhokama qilamiz va namoyish qilamiz.
Manba: www.habr.com
