← Crossware Engineering Hub / Articles
Qt for MCUs · Traveo T2G class target

From .qml to silicon build, flash, execute, allocate

Eight stages tracing a Qt Quick Ultralite application from source through ahead-of-time compilation, into internal and external flash, up into RAM at boot, and out to the display controller. Worked figures come from a 1280×768 CYT4DN cluster build.

Source AOT compiler Generated C++ Object files MainScreen.qmlelement tree MainScreen.cpp+ MainScreen.h MainScreen.o.text .rodata .bss Gauge.qml+ inline JS bindings Gauge.cppJS expr → C++ functors Gauge.obinding code + nodes qml_registry.cpproot instantiation registry.o qmltocpp resolves types flattens element tree translates JS subset emits dependency nodes sizes everything now no engine on target kinematics.cpphand-written C++ kinematics.o no QML step — straight to the compiler Target C++ compiler arm-none-eabi-gcc · GHS ELXR · IAR · ARMCLANG every .cpp above passes through here
Artwork gauge_bg.png1150 × 215 needle_seq/*.pngsprite sequence icon_*.pngalpha masks qulrcc resource compiler → layer pixel format RGB565 · RGB32 · Alpha8 optional lossless compression prescale / rotate baked in images only — not fonts Placement chosen in the build files resource blob → external flash read in place over SMIF while blitting costs zero RAM if uncompressed if compressed → decoded at runtime needs an image cache slot in RAM plus CPU time on first use const arrays → internal flash .rodata for small or boot-critical images also read in place
Font inputs Roboto.ttfvector outlines character setstring literals in QML+ translations, or explicit font sizes in usefrom font.pixelSize valuesfound in the project font compiler build-time step separate from qulrcc output depends on the configured font engine Static font engine glyphs rasterised on the HOST bitmaps for that charset × those sizes stored in flash as const data runtime: blit the bitmap directly no rasteriser · no glyph cache fixed sizes only · flash grows with charset Vector font engine (Monotype Spark) outlines subset and embedded as a blob internal or external flash · no bitmaps baked runtime: rasterise each glyph on demand → glyph cache + text layout cache in RAM any size · scaling · smaller flash costs RAM and CPU per new glyph
Link inputs *.o from stage 01 libQulCore libQulControls / Shapes platform portlayer engine · OTF/LBO · DMA hooks font engine library BSP / HAL · SMIF · display FreeRTOS or bare metal C runtime · startup linker + script assigns every section to a physical region the memory architecture is decided right here app.elf+ map file app.hexinternal flash image resources.binexternal flash image
kinematics.cpphand-written C++
float solveIK(const Pose &p) { … 40 lines … }
.textinternal flash · XIP
static const float kArmLength[6] = { 1.2f, 0.9f, … };
.rodataread in place
static int calibOffset = 42;
.data imgcopied to SRAM
static float jointAngle[6];
.bssno flash cost
MainScreen.qml → MainScreen.cpp → MainScreen.ogenerated
Rectangle { … } — the object instance itself
.bsspermanent RAM
construction + property-set code for that tree
.textinternal flash
Text { text: "SPEED" } — the literal
.rodatainternal flash
text: speed * 1.6 — JS binding, now a C++ functor
.text+ node in .bss
Image { source: "gauge_bg.png" } — pixel data
resource blobexternal flash
Assetsfrom stages 02 and 03
gauge_bg.png — large, uncompressed
resource blobread in place
icon_warn.png — small, boot-critical
.rodatainternal flash
Roboto — static engine: baked glyph bitmaps
.rodatainternal flash
Roboto — vector engine: subsetted outlines
font blobexternal flash

Internal code flash · memory mapped · executable4 MB
vectors
.text — solveIK, MainScreen ctor, binding functors, Qul core, platform port
.rodata — kArmLength, "SPEED", icon_warn, static glyphs
.data img — calibOffset
unused
programmed as app.hex
External flash over SMIF · memory mapped · read-onlyQSPI / HyperFlash
resource blob — gauge_bg.png, needle_seq, atlases
font outline blob
streamed map tiles
unused
programmed separately as resources.bin
CM7 core I-cache · prefetch D-cache Internal flash vectors .text stays here executed in place .rodata stays here .data image .ramfunc image unused SRAM .data .bss — zeroed QML object tree no flash source stacks .ramfunc / TCM free heap .data → copy .ramfunc → copy instruction fetch const reads data access External flash resource blob stays here font blob stays here texture reads VRAM buffers + caches claimed at platform init separate region
moves flash → SRAM at startup stays in flash, read in place stays in external flash claimed, never copied
Renderer Qul repaint CPU rasteriser + 2D blitter / DMA writes the back buffer VRAM — its own linker region BACK BUFFER being drawn into w × h × bytes per pixel owned by the renderer FRONT BUFFER read-only for this whole frame owned by the display controller roles swap on vertical blank additional layer buffers smaller regions, composited by hardware image cache only for resources not readable in place glyph cache + text layout cache present only with a vector font engine sized at build time, reserved up front pixel stream Display controller DMA reads the front buffer at the pixel clock, continuously Panel1280 × 768 LVDS external flash textures · outlines
VRAM region — dedicated, does not touch the heap2 MB · 96% occupied
front + back buffers
additional layer buffers
image + glyph + text caches
~83 KB
claimed statically at platform init — never malloc'd

System SRAM — the heap comes from hereheap = the remainder
.data
.bss — Qul object tree · dependency node pool
task + core stacks
.ramfunc / TCM
driver + RTOS buffers
free heap
fixed at link time available for allocation
ConsumerRegionFixed atReduces heap?
Layer / frame buffersVRAMplatform initno — separate region
Image / glyph / text cachesVRAMbuild configno — separate region
.data + .bssSRAMlink timeyes
Task and core stacksSRAMlink / RTOS configyes
RAM-resident functionsSRAM / TCMlinker scriptyes
Free heapSRAMwhatever survivesthe remainder