Portación de Qt a STM32

Portación de Qt a STM32¡Buenos días! Estamos en el proyecto Embox hemos lanzado Qt en STM32F7-Discovery y nos gustaría contarte sobre ello. Anteriormente, ya hemos hablado de cómo logramos iniciar OpenCV.

Qt es un framework multiplataforma que incluye no solo componentes gráficos, sino también elementos como QtNetwork, un conjunto de clases para trabajar con bases de datos, Qt for Automation (incluyendo para la implementación de IoT) y mucho más. Los desarrolladores del equipo de Qt ya previeron el uso de Qt en sistemas embebidos, por lo que las bibliotecas están bastante bien configuradas. Sin embargo, hasta hace poco, pocos pensaban en portar Qt a microcontroladores, probablemente porque tal tarea parece complicada: Qt es grande, los MCU son pequeños.

Por otro lado, actualmente existen microcontroladores diseñados para trabajar con multimedia que superan a los primeros Pentium. Hace aproximadamente un año, apareció en el blog de Qt publicación. Los desarrolladores portaron Qt a OS RTEMS y lanzaron ejemplos con widgets en varias placas bajo STM32F7. Esto nos interesó. Se notó, y los propios desarrolladores lo mencionan, que Qt funciona lento en STM32F7-Discovery. Nos preguntamos si podríamos iniciar Qt bajo Embox, no solo dibujar un widget, sino ejecutar una animación.

Qt 4.8 ya ha sido portado a Embox desde hace tiempo, así que decidimos probarlo. Elegimos la aplicación moveblocks — un ejemplo de animación elástica.

Qt moveblocks en QEMUPortación de Qt a STM32

Primero configuramos Qt con el conjunto de componentes más mínimo necesario para soportar la animación. Para ello existe la opción “-qconfig minimal,small,medium ...”. Esta opción conecta un archivo de configuración de Qt que contiene muchos macros — qué incluir / qué excluir. Después de esta opción, añadimos otros flags en la configuración si queremos desactivar aún más cosas. Aquí hay un ejemplo de nuestra configuración.

Para que Qt funcione, es necesario añadir una capa de compatibilidad con el sistema operativo. Una de las formas es implementar QPA (Qt Platform Abstraction). Usamos un plugin ya existente, fb_base, que forma parte de Qt, sobre el cual funciona QPA para Linux. Al final, surgió un pequeño plugin emboxfb, que proporciona a Qt el framebuffer de Embox, y después hace el dibujo allí sin ayuda externa.

Así es como se ve la creación de un 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 (fbFd setPhysicalSize(QSize(fbWidth, fbHeight));
    mScreens.append(mPrimaryScreen);

    this->printFbInfo();
}

Así es como se verá la redibujación

QRegion QEmboxFbScreen::doRedraw()
{
    QVector rects;
    QRegion touched = QFbScreen::doRedraw();

    DPRINTF("QEmboxFbScreen::doRedrawn");

    if (!compositePainter) {
        compositePainter = new QPainter(mFbScreenImage);
    }

    rects = touched.rects();
    for (int i = 0; i drawImage(rects[i], *mScreenImage, rects[i]);
    }
    return touched;
}

Al final, con la optimización del compilador habilitada para el tamaño de la memoria -Os, la imagen de la biblioteca resultó ser de 3.5 MB, lo que, por supuesto, no cabe en la memoria principal del STM32F746. Como ya mencionamos en otro artículo sobre OpenCV, en esta placa hay:

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

Dado que ya se había agregado soporte para la ejecución de código desde QSPI para OpenCV, decidimos comenzar cargando la imagen de Embox con Qt completamente en QSPI. Y, ¡hurra!, casi todo se inició de inmediato desde QSPI. Pero, como en el caso de OpenCV, resultó que era demasiado lento.

Portación de Qt a STM32

Así que decidimos hacer lo siguiente: primero copiamos la imagen en QSPI, luego la cargamos en SDRAM y ejecutamos desde allí. Desde SDRAM fue un poco más rápido, pero aún estaba lejos de QEMU.

Portación de Qt a STM32

Luego surgió la idea de habilitar la coma flotante, ya que Qt realiza algunos cálculos de las coordenadas de los cuadros en la animación. Lo intentamos, pero no obtuvimos una aceleración visible, aunque en el artículo los desarrolladores de Qt afirmaron que la FPU proporciona un aumento significativo en la velocidad para la “animación de arrastre” en pantallas táctiles. Tal vez, en moveblocks hay significativamente menos cálculos con punto flotante, y esto depende del ejemplo específico.

La idea más efectiva resultó ser trasladar el framebuffer de SDRAM a la memoria interna. Para ello, configuramos las dimensiones de la pantalla a 272×272 en lugar de 480×272. Además, reducimos la profundidad de color de A8R8G8B8 a R5G6B5, de este modo disminuyendo el tamaño de un píxel de 4 a 2 bytes. Obtuvimos un tamaño de framebuffer de 272 * 272 * 2 = 147968 bytes. Esto proporcionó una aceleración significativa, probablemente la más notable, la animación se volvió casi fluida.

La última optimización fue la ejecución del código de Embox desde RAM y de Qt desde SDRAM. Para esto, primero vinculamos estáticamente Embox junto con Qt, pero colocamos los segmentos text, rodata, data y bss de la biblioteca en QSPI, para luego copiarlos a 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))

Al ejecutar el código de Embox desde ROM también obtuvimos una aceleración notable. Como resultado, la animación resultó bastante fluida:

Reproducir video

Ya al final, al preparar el artículo y probar diferentes configuraciones de Embox, descubrimos que Qt moveblocks funciona maravillosamente desde QSPI con framebuffer en SDRAM, siendo el verdadero cuello de botella el tamaño del framebuffer. Al parecer, para superar el inicial “slideshow” bastó con una aceleración de 2 veces simplemente mediante la reducción del tamaño del framebuffer. No se logró tal resultado únicamente trasladando el código de Embox a diferentes memorias rápidas (la aceleración resultó no ser de 2, sino aproximadamente de 1.5 veces).

Cómo intentarlo tú mismo

Si tienes un STM32F7-Discovery, puedes ejecutar Qt bajo Embox tú mismo. Puedes leer cómo hacerlo en nuestro wiki.

Conclusión

Finalmente, ¡logramos ejecutar Qt! La dificultad de la tarea, en nuestra opinión, ha sido algo exagerada. Por supuesto, es necesario tener en cuenta la especificidad de los microcontroladores y entender la arquitectura de los sistemas de computación. Los resultados de la optimización indican un hecho conocido, que el área más restringida en un sistema de computación no es el procesador, sino la memoria.

Este año participaremos en el festival TechTrain. Allí contaremos más detalles y mostraremos Qt, OpenCV en microcontroladores y otros logros nuestros.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster