ترقية كيو تي إلى STM32

مساء الخير في مشروع Embox ، أطلقنا Qt على STM32F7-Discovery ونود أن نخبره. في وقت سابق ، أخبرنا بالفعل كيف تمكنا من إطلاق OpenCV .

Qt عبارة عن إطار عمل مشترك بين الأنظمة الأساسية لا يتضمن مكونات رسومية فحسب ، بل يشمل أيضًا أشياء مثل QtNetwork ومجموعة من الفئات للعمل مع قواعد البيانات و Qt for Automation (بما في ذلك تطبيق IoT) ، وأكثر من ذلك بكثير. توقع مطورو فريق Qt استخدام Qt في الأنظمة المدمجة ، بحيث يتم تكوين المكتبات بشكل جيد. ومع ذلك ، حتى وقت قريب ، فكر عدد قليل من الناس في نقل Qt إلى ميكروكنترولر ، ربما لأن هذه المهمة تبدو معقدة - Qt كبيرة ، MCUs صغيرة.

من ناحية أخرى ، يوجد في الوقت الحالي ميكروكنترولر مصممة للعمل مع الوسائط المتعددة وتتفوق على أجهزة بنتيوم الأولى. منذ حوالي عام ، ظهرت مشاركة في مدونة Qt. قام المطورون بإنشاء منفذ Qt تحت نظام RTEMS OS ، وأطلقوا أمثلة مع عناصر واجهة مستخدم على العديد من اللوحات التي تعمل على stm32f7. انها مهتمة بنا. كان ملحوظًا ، والمطورين أنفسهم يكتبون عن هذا أن Qt يبطئ في STM32F7-Discovery. تساءلنا عما إذا كان بإمكاننا تشغيل Qt تحت Embox ، وليس فقط رسم عنصر واجهة تعامل مستخدم ، ولكن أيضًا بدء تشغيل الرسوم المتحركة.

تم Embt ترقية Qt 4.8 لفترة طويلة ، لذلك قررنا أن نحاول ذلك. اخترنا تطبيق moveblocks - مثال على الرسوم المتحركة springy.

الحواجز QT على QEMU


بادئ ذي بدء ، نقوم بتكوين كيو تي ، إن أمكن ، مع الحد الأدنى من مجموعة المكونات اللازمة لدعم الرسوم المتحركة. لهذا هناك خيار "تكوين الحد الأدنى والصغيرة والمتوسطة ...". ويشمل ملف التكوين من كيو تي مع العديد من وحدات الماكرو - ما لتمكين / تعطيل. بعد هذا الخيار ، أضف إشارات أخرى إلى التكوين إذا كنا نريد تعطيل شيء آخر. هنا مثال على التكوين الخاص بنا.

لكي تعمل Qt ، تحتاج إلى إضافة طبقة توافق OS. طريقة واحدة هي تطبيق QPA (Qt Platform Abstraction). الأساس هو fb_base المكون الإضافي الجاهز في Qt ، والذي يعمل على أساسه QPA لنظام Linux. والنتيجة هي البرنامج المساعد emboxfb الصغيرة التي توفر Framebuffer Embox ، ومن ثم يرسم هناك بالفعل دون أي مساعدة.

هذه هي الطريقة التي يبدو إنشاء البرنامج المساعد
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::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; } 


نتيجة لذلك ، مع التحسين المترجم للمترجم لحجم الذاكرة- Os ، تحولت صورة المكتبة إلى 3.5 ميغابايت ، والتي بالطبع لا تنسجم مع الذاكرة الرئيسية STM32F746. كما كتبنا بالفعل في مقالتنا الأخرى حول OpenCV ، يحتوي هذا المنتدى على:

  • 1 ميغابايت ROM
  • 320 كيلو بايت من ذاكرة الوصول العشوائي
  • 8 ميغابايت SDRAM
  • 16 ميجابايت QSPI

نظرًا لأن دعم تنفيذ التعليمات البرمجية من QSPI قد تمت إضافته بالفعل لـ OpenCV ، فقد قررنا البدء بتحميل صورة Embox c Qt بالكامل في QSPI. يا له من أمر ، بدأ كل شيء على الفور من QSPI! ولكن كما هو الحال مع OpenCV ، اتضح أنها بطيئة للغاية.



لذلك ، قررنا القيام بذلك - أولاً قم بنسخ الصورة إلى QSPI ، ثم تحميلها في SDRAM وتنفيذها من هناك. من SDRAM أصبح أسرع قليلاً ، لكن لا يزال بعيدًا عن QEMU.



بعد ذلك كانت فكرة تضمين نقطة عائمة - لأن Qt تقوم ببعض العمليات الحسابية لإحداثيات المربعات في الرسوم المتحركة. لقد جربوها ، لكنهم لم يحصلوا على تسارع مرئي ، على الرغم من أن مطوري كيو تي زعموا في المقال أن FPU توفر زيادة كبيرة في سرعة "سحب الرسوم المتحركة" على الشاشة التي تعمل باللمس. ربما يكون لقوائم النقل عدد أقل بكثير من حسابات الفاصلة العائمة ، وهذا يعتمد على مثال محدد.

كانت الفكرة الأكثر فاعلية هي نقل الأداة Framebuffer من SDRAM إلى الذاكرة الداخلية. للقيام بذلك ، لم يكن لدينا حجم شاشة 480 × 272 ، ولكن 272 × 272. قمنا أيضًا بتقليل عمق الألوان من A8R8G8B8 إلى R5G6B5 ، وبالتالي تقليل حجم بكسل واحد من 4 إلى 2 بايت. حصلنا على حجم framebuffer 272 * 272 * 2 = 147968 بايت. أعطى هذا تسارع كبير ، وربما الأكثر بروزا ، الرسوم المتحركة أصبحت سلسة تقريبا.

وكان التحسين الأخير هو تنفيذ كود Embox من RAM ، و Qt من SDRAM. للقيام بذلك ، نقوم أولاً ، كالعادة ، بربط 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)) 

بسبب تنفيذ التعليمات البرمجية ، تلقى Embox من ROM أيضًا تسارعًا ملموسًا. نتيجة لذلك ، اتضح أن الرسوم المتحركة سلسة للغاية:


بالفعل ، في النهاية ، أثناء إعداد مقال ومحاولة تكوينات متنوعة لـ Embox ، اتضح أن حواجز نقل الحركة Qt تعمل بشكل جيد من QSPI مع أداة ضبط إطارات في SDRAM ، وكان حجم أداة إلغاء ضغط الإطارات هو عنق الزجاجة! على ما يبدو ، للتغلب على "عرض الشرائح" الأولي ، كان التسارع 2 مرات كافيًا نظرًا لتقليص حجم الإطار المعدني بشكل عادي. لكن لم يكن من الممكن تحقيق مثل هذه النتيجة عن طريق نقل رمز Embox فقط إلى ذاكرة سريعة متنوعة (لم يتم الحصول على التسارع بمقدار 2 ، ولكن بنحو 1.5 مرة).

كيف تحاول ذلك بنفسك


إذا كان لديك STM32F7-Discovery ، يمكنك تشغيل Qt تحت Embox بنفسك. يمكنك قراءة كيفية القيام بذلك على الويكي الخاصة بنا.

استنتاج


نتيجة لذلك ، تمكنا من إطلاق كيو تي! تعقيد المهمة ، في رأينا ، مبالغ فيه إلى حد ما. بطبيعة الحال ، تحتاج إلى أن تأخذ في الاعتبار تفاصيل ميكروكنترولر وفهم بنية أنظمة الحوسبة بشكل عام. تشير نتائج التحسين إلى حقيقة معروفة وهي أن عنق الزجاجة في نظام الحوسبة ليس المعالج ، ولكن الذاكرة.

سنشارك هذا العام في مهرجان TechTrain . هناك سوف نقول بمزيد من التفاصيل ونعرض كيو تي ، OpenCV على ميكروكنترولر وإنجازاتنا الأخرى.

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


All Articles