Bom dia! Estamos no projeto e lançamos o Qt no STM32F7-Discovery e gostaríamos de compartilhar sobre isso. Anteriormente, já falamos sobre como conseguimos rodar .
O Qt é um framework multiplataforma que abrange não apenas componentes gráficos, mas também assuntos como QtNetwork, um conjunto de classes para trabalhar com bancos de dados, Qt for Automation (incluindo para implementação de IoT) e muito mais. Os desenvolvedores da equipe Qt anteciparam o uso do Qt em sistemas embarcados, portanto, as bibliotecas são bastante configuráveis. No entanto, até recentemente, poucas pessoas pensaram na portabilidade do Qt para microcontroladores, provavelmente porque essa tarefa parece complexa — o Qt é grande, enquanto os MCUs são pequenos.
Por outro lado, atualmente existem microcontroladores projetados para trabalhar com multimídia que superam os primeiros Pentium. Cerca de um ano atrás, no blog do Qt, surgiu . Os desenvolvedores portaram o Qt para o sistema operacional RTEMS e executaram exemplos com widgets em várias placas controladas pelo stm32f7. Isso nos interessou. Era evidente, e os desenvolvedores mencionam isso, que o Qt tem um desempenho lento no STM32F7-Discovery. Ficamos curiosos se conseguiríamos rodar o Qt sob o Embox, não apenas desenhando um widget, mas também rodando uma animação.
O Qt 4.8 já estava portado para o Embox há bastante tempo, então decidimos tentar com ele. Escolhemos o aplicativo moveblocks — um exemplo de animação elástica.
Qt moveblocks no QEMU
Primeiro, configuramos o Qt com o conjunto mínimo de componentes necessários para suportar animação. Para isso, existe a opção “-qconfig minimal,small,medium …”. Ela conecta um arquivo de configuração do Qt com uma série de macros — o que incluir / o que desativar. Após essa opção, adicionamos outros flags à configuração se quisermos desativar mais alguma coisa. Aqui está um exemplo da nossa .
Para que o Qt funcione, é necessário adicionar uma camada de compatibilidade com o sistema operacional. Uma das formas é implementar o QPA (Qt Platform Abstraction). Nós usamos como base um plugin já existente chamado fb_base dentro do Qt, sobre o qual funciona o QPA para Linux. No final, resultou em um pequeno plugin emboxfb, que fornece ao Qt o framebuffer do Embox, e a partir daí ele desenha sem ajuda externa.
Assim é como parece a criação de um 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();
}
Assim será a aparência do redesenho
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;
}
Como resultado, com a otimização de compilação para uso de memória -Os, a imagem da biblioteca ficou 3,5 MB, o que, evidentemente, não cabe na memória principal do STM32F746. Como já mencionamos em nosso outro artigo sobre OpenCV, neste placa há:
- 1 MB de ROM
- 320 KB de RAM
- 8 MB de SDRAM
- 16 MB de QSPI
Como o suporte para execução de código a partir do QSPI já havia sido adicionado para o OpenCV, decidimos começar carregando a imagem do Embox com Qt no QSPI completamente. E, finalmente, quase tudo funcionou imediatamente do QSPI! Mas, como no caso do OpenCV, percebeu-se que funcionava muito lentamente.

Portanto, decidimos proceder da seguinte forma — primeiro copiamos a imagem para o QSPI, depois a carregamos na SDRAM e executamos a partir daí. A partir da SDRAM, ficou um pouco mais rápido, mas ainda assim longe do QEMU.

A seguir, surgiu a ideia de incluir ponto flutuante — afinal, o Qt realiza alguns cálculos de coordenadas dos quadrados na animação. Fizemos o teste, mas não obtivemos aceleração visível, embora os desenvolvedores do Qt afirmassem que o FPU oferece um aumento significativo na velocidade para "animações de arrastar" em telas sensíveis ao toque. Pode ser que em moveblocks haja consideravelmente menos cálculos com ponto flutuante, e isso depende do exemplo específico.
A ideia mais eficaz foi transferir o framebuffer da SDRAM para a memória interna. Para isso, fizemos as dimensões da tela não 480×272, mas 272×272. Também reduzimos a profundidade de cor de A8R8G8B8 para R5G6B5, diminuindo assim o tamanho de um pixel de 4 para 2 bytes. Obtivemos o tamanho do framebuffer de 272 * 272 * 2 = 147968 bytes. Isso proporcionou um aumento significativo de desempenho, talvez o mais notável, e a animação se tornou quase suave.
A última otimização foi a execução do código do Embox da RAM, enquanto o Qt foi executado da SDRAM. Para isso, primeiro, vinculamos estaticamente o Embox junto com o Qt, mas os segmentos text, rodata, data e bss da biblioteca foram alocados no QSPI, para que depois pudéssemos copiar para 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))
A execução do código do Embox a partir da ROM também resultou em um aumento de desempenho significativo. Como resultado, a animação ficou bastante suave:

Já no final, enquanto preparávamos o artigo e experimentávamos várias configurações do Embox, descobrimos que o Qt moveblocks funciona maravilhosamente bem tanto no QSPI quanto no framebuffer na SDRAM, e o gargalo estava realmente no tamanho do framebuffer! Parece que para superar o inicial "slide show" um aumento de 2 vezes foi suficiente apenas com a diminuição banal do tamanho do framebuffer. E alcançar tal resultado transferindo apenas o código do Embox para diferentes memórias rápidas não foi possível (o aumento foi de cerca de 1,5 vezes, não 2).
Como experimentar por conta própria
Se você possui o STM32F7-Discovery, pode executar o Qt sob o Embox por conta própria. Você pode ler como isso é feito em nosso .
Conclusão
No final, conseguimos executar o Qt! A dificuldade da tarefa, na nossa opinião, foi um pouco exagerada. Naturalmente, é preciso levar em consideração a especificidade dos microcontroladores e entender a arquitetura dos sistemas computacionais. Os resultados da otimização destacam o fato conhecido de que o ponto mais fraco em um sistema computacional não é o processador, mas a memória.
Este ano, estaremos participando do festival . Lá vamos explicar e mostrar em mais detalhes o Qt, OpenCV em microcontroladores e outras conquistas nossas.
Fonte: habr.com
