عصر بخیر ما در پروژه هستیم
Qt یک چارچوب بین پلتفرمی است که نه تنها شامل اجزای گرافیکی، بلکه مواردی مانند QtNetwork، مجموعهای از کلاسها برای کار با پایگاههای داده، Qt برای اتوماسیون (از جمله برای پیادهسازی اینترنت اشیا) و موارد دیگر است. تیم Qt در مورد استفاده از Qt در سیستمهای جاسازی شده فعال بوده است، بنابراین کتابخانهها کاملاً قابل تنظیم هستند. با این حال، تا همین اواخر، افراد کمی در مورد انتقال Qt به میکروکنترلرها فکر می کردند، احتمالاً به این دلیل که چنین کاری دشوار به نظر می رسد - Qt بزرگ است، MCU ها کوچک هستند.
از سوی دیگر، در حال حاضر میکروکنترلرهایی برای کار با چند رسانه ای و برتر از پنتیوم های اول طراحی شده اند. حدود یک سال پیش، وبلاگ Qt ظاهر شد
Qt 4.8 برای مدت طولانی به Embox پورت شده است، بنابراین تصمیم گرفتیم آن را روی آن امتحان کنیم. ما برنامه moveblocks را انتخاب کردیم - نمونه ای از انیمیشن فنری.
بلوک های حرکتی Qt در QEMU
برای شروع، در صورت امکان، Qt را با حداقل مجموعه ای از اجزای مورد نیاز برای پشتیبانی از انیمیشن پیکربندی می کنیم. برای این گزینه "-qconfig حداقل، کوچک، متوسط..." وجود دارد. این یک فایل پیکربندی از Qt را با ماکروهای زیادی متصل می کند - چه چیزی را فعال کنید / چه چیزی را غیرفعال کنید. بعد از این گزینه، اگر بخواهیم چیز دیگری را غیرفعال کنیم، پرچم های دیگری را به پیکربندی اضافه می کنیم. در اینجا یک نمونه از ما است
برای اینکه Qt کار کند، باید یک لایه سازگاری سیستم عامل اضافه کنید. یکی از راه ها پیاده سازی QPA (Qt Platform Abstraction) است. ما پلاگین آماده fb_base موجود در Qt را به عنوان پایه در نظر گرفتیم که بر اساس آن QPA برای لینوکس کار می کند. نتیجه یک پلاگین کوچک به نام emboxfb است که فریم بافر Embox را به Qt ارائه می کند و سپس بدون هیچ کمک خارجی به آنجا رسم می کند.
این چیزی است که ایجاد یک افزونه به نظر می رسد
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 مگابایتی
- رم 320 کیلوبایت
- 8 مگابایت SDRAM
- 16 مگابایت QSPI
از آنجایی که پشتیبانی از اجرای کد از QSPI قبلاً به OpenCV اضافه شده است، تصمیم گرفتیم با بارگیری کل تصویر Embox c Qt در QSPI شروع کنیم. و هورای، همه چیز تقریباً بلافاصله از QSPI شروع شد! اما همانطور که در مورد OpenCV، معلوم شد که خیلی کند کار می کند.
بنابراین، تصمیم گرفتیم این کار را به این صورت انجام دهیم - ابتدا تصویر را در QSPI کپی می کنیم، سپس آن را در SDRAM بارگذاری می کنیم و از آنجا اجرا می کنیم. از SDRAM کمی سریعتر شد، اما هنوز با QEMU فاصله دارد.
بعد، ایده ای برای گنجاندن یک نقطه شناور وجود داشت - بالاخره Qt محاسبات مختصات مربع ها را در انیمیشن انجام می دهد. ما تلاش کردیم، اما در اینجا هیچ شتاب قابل مشاهده ای دریافت نکردیم، هرچند در
موثرترین ایده انتقال فریم بافر از SDRAM به حافظه داخلی بود. برای این کار، ابعاد صفحه را نه 480x272، بلکه 272x272 ساختیم. همچنین عمق رنگ را از A8R8G8B8 به R5G6B5 کاهش دادیم، بنابراین اندازه یک پیکسل را از 4 به 2 بایت کاهش دادیم. اندازه فریم بافر حاصل 272 * 272 * 2 = 147968 بایت است. این شتاب قابل توجهی به همراه داشت، شاید از همه مهمتر این بود که انیمیشن تقریبا صاف شد.
آخرین بهینه سازی اجرای کد Embox از رم و کد Qt از SDRAM بود. برای انجام این کار، ابتدا، طبق معمول، Embox را به صورت ایستا با Qt پیوند می دهیم، اما بخش های متن، rodata، داده و 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))
با اجرای کد Embox از رام شتاب محسوسی نیز دریافت کردیم. در نتیجه، انیمیشن کاملاً روان شد:
در انتها، در حین آماده سازی مقاله و آزمایش پیکربندی های مختلف Embox، مشخص شد که بلوک های حرکتی Qt از QSPI با یک فریم بافر در SDRAM عالی کار می کنند و گلوگاه دقیقاً به اندازه فریم بافر بود! ظاهراً برای غلبه بر "نمایش اسلاید" اولیه، یک شتاب 2 برابری به دلیل کاهش پیش پا افتاده اندازه فریم بافر کافی بود. اما دستیابی به چنین نتیجه ای با انتقال تنها کد Embox به حافظه های سریع مختلف ممکن نبود (شتاب 2، بلکه حدود 1.5 برابر بود).
چگونه خودتان آن را امتحان کنید
اگر STM32F7-Discovery دارید، میتوانید Qt را خودتان در Embox اجرا کنید. می توانید نحوه انجام این کار را در ما بخوانید
نتیجه
در نتیجه موفق شدیم Qt را راه اندازی کنیم! پیچیدگی کار، به نظر ما، تا حدودی اغراق آمیز است. به طور طبیعی، شما باید ویژگی های میکروکنترلرها را در نظر بگیرید و به طور کلی معماری سیستم های کامپیوتری را درک کنید. نتایج بهینه سازی به این واقعیت معروف اشاره می کند که گلوگاه در یک سیستم محاسباتی پردازنده نیست، بلکه حافظه است.
امسال در جشنواره شرکت خواهیم کرد
منبع: www.habr.com