Reduce Embedded GUI Memory Usage

Running out of RAM is the most common integration failure in embedded GUI projects. This page explains exactly where GUI memory goes, gives concrete numbers for a 320×240 display, and shows six techniques to shrink your footprint without sacrificing display quality.

What Uses the Most RAM in an Embedded GUI?

Embedded GUI memory usage has three main components: framebuffer RAM (pixel storage for the display), widget state RAM (active widget objects and their properties), and asset RAM (decoded font glyphs and image data held at runtime). Of these, the framebuffer dominates. A 320×240 display at 16-bit colour (RGB565) requires exactly 153,600 bytes — 150 KB — for a single framebuffer. Double-buffering doubles this to 300 KB, exceeding the internal SRAM of most cost-effective MCUs entirely. Engineers typically discover this constraint during board bring-up, when the linker reports an overflow of the .bss or heap section.

Sparklet provides six independent techniques to address each component of memory usage — applicable individually or in combination depending on available hardware. The highest-impact single change (switching to partial buffer mode) reduces framebuffer RAM from 150 KB to as little as 6.4 KB — a 24× saving before any other optimisation is applied. For performance impact alongside memory optimisation, see Fix Slow Embedded GUI Performance. For per-platform RAM and Flash benchmarks, see Performance & Memory Benchmarks.

The Memory Budget Problem in Numbers

Consider an STM32F4 with 192 KB internal SRAM. A 320×240 RGB565 display needs 150 KB for a single framebuffer. That leaves 42 KB for the Sparklet core (~16 KB minimum), FreeRTOS task stacks (8–16 KB), RTOS kernel objects (~4 KB), and all communication and sensor buffers. The numbers do not add up with a naïve implementation — but they can with the right combination of the techniques on this page.

Four Memory Reduction Strategies

Each technique targets a different component of total embedded GUI memory usage — apply them independently or in combination for maximum savings.

Framebuffer RAM: From 150 KB to Under 7 KB With Partial Buffer Mode

The framebuffer is the single largest RAM consumer in any embedded GUI project. For a 320×240 RGB565 display, a full framebuffer requires 150 KB. The most impactful single change is switching to partial buffer mode — Sparklet allocates a strip buffer covering only a configurable number of scan lines and makes multiple renderer passes per frame, flushing each strip via DMA while computing the next.

Strip sizes and their framebuffer RAM costs for a 320-wide RGB565 display:

  • Full framebuffer (240 lines): 150 KB
  • 32-line strip: 320 × 32 × 2 = 20 KB
  • 16-line strip: 320 × 16 × 2 = 10 KB
  • 10-line strip: 320 × 10 × 2 = 6.4 KB (minimum practical for most displays)

This 24× reduction is the single most impactful memory saving available. CPU overhead increases slightly due to multi-pass rendering, but hardware DMA transfers overlap with the next strip computation, keeping net throughput loss typically below 15%. Strip height is a single parameter in the Sparklet HAL initialisation call.

Memory Breakdown: 320×240 RGB565 Display — Before and After Optimisation

ComponentTypical UsageSparklet MinimumReduction Technique
Framebuffer RAM150 KB (single full frame)6.4 KB (10-line partial, 16-bit)Partial buffer mode
Widget core RAM30–80 KB (all 36+ widget types)~16 KB (selective inclusion)Feature flags in sparklet_config.h
Font assets (Flash)80–120 KB per font face20–40 KB (compressed)Sparklet compressed font format
Image assets (Flash)150 KB per full-screen RGB565 image15–40 KB (PNG compressed)PNG storage + decode-at-render
List widget RAM1000 × widget size (full list)12 × widget size (virtual scroll)Widget pooling in ScrollView/ListView
Double-buffer overhead+150 KB for tear-free display0 KB extra (dirty-region)Dirty-region rendering avoids double-buffer need

Sparklet Memory Optimisation Features

Dirty-Region Saves Double-Buffer RAM

Sparklet's dirty-region renderer eliminates the need for a double framebuffer in most applications. Double buffering — two full framebuffers for tear-free display — is only necessary when full-screen transitions happen at high frame rates continuously. For typical embedded UIs where partial areas update incrementally, Sparklet's dirty-region rendering delivers tear-free output with a single framebuffer — saving 150 KB at 320×240 RGB565 compared to a naive double-buffered implementation. See Fix Slow GUI Performance for the full render pipeline explanation.

Compressed Font & Image Assets

Flint UI Designer compresses all font and image assets at export time into Sparklet's binary format. Font glyph data is stored compressed and decompressed into a runtime glyph cache on first character use. PNG images are decoded from Flash at render time into a small decode buffer (5–10 KB). Together these two techniques reduce asset Flash footprint by 50–70% with no design workflow changes — assets are compressed automatically during the Flint export step. Flint's real-time asset size panel shows per-asset Flash consumption throughout the design phase so overruns are caught before building.

Selective Widget Compilation

Sparklet's build system allows individual widget types to be excluded via feature flags in sparklet_config.h. Each excluded widget type removes its renderer, event handler, property descriptors, and static tables from the binary. An application that uses only 8 of Sparklet's 36+ widget types can exclude the other 28, reducing the library Flash footprint proportionally. Typical code-size saving per excluded widget type: 2–8 KB of Flash. The Flint UI Designer project defines which widget types are used — the build system validates that no excluded widget type is referenced. See the full catalogue at Widget Library.

How to Fit Embedded GUI Into 32 KB RAM

A validated configuration achieving a sub-32 KB total RAM footprint on Cortex-M0+ and Cortex-M3 targets with SPI LCD, using a combination of four techniques.
Partial Buffer

Partial Buffer — 10 Scan Lines

For a 320-wide 8-bit display, a 10-line partial buffer requires 320 × 10 × 1 = 3.2 KB. At 16-bit depth this is 6.4 KB. This eliminates the full 150 KB framebuffer requirement entirely. The renderer makes 24 passes per frame (240 lines ÷ 10), each flushed to the SPI display controller via DMA. Strip height is configured in the Sparklet HAL init call — no other code change required.

8-bit Colour

8-bit Colour Depth

Switching from 16-bit to 8-bit colour halves framebuffer RAM and is visually acceptable for status indicators, appliance panels, and simple HMIs. Sparklet's 8-bit renderer supports both palette-mapped colour (up to 256 colours) and greyscale modes. Palette selection is configured at project level in Flint. Combined with a 10-line partial buffer, total framebuffer RAM for a 320-wide display drops to 3.2 KB.

Selective Widgets

Selective Widget Inclusion

Including only the widget types used in the application reduces the Sparklet core RAM requirement substantially. For a simple status panel using Button, TextArea, ProgressBar, and ImageHolder, excluding the remaining 30+ widget types reduces the library to approximately 10–14 KB of Flash and 12–14 KB of RAM — well below the 16 KB minimum figure for an all-widget build.

Stack Budget

RTOS Task Stack Budget

Sparklet's render task stack requirement is 1–2 KB with a minimal widget tree. Allocating 2 KB for the Sparklet render task, 4 KB for the application task, and 2 KB for the RTOS idle task gives a total task stack budget of 8 KB — well within a 32 KB total RAM target alongside the Sparklet core and partial buffer. See RTOS Support for FreeRTOS integration details.

FAQs — Reducing Embedded GUI Memory

The highest-impact single change is switching from a full-screen framebuffer to partial buffer rendering. This alone reduces framebuffer RAM from 150 KB (320×240 RGB565) to as little as 6.4 KB — a 24× reduction. Combine this with 16-bit or 8-bit colour depth, compressed fonts exported by Flint, selective widget inclusion, and widget pooling for list-heavy UIs. Sparklet supports all of these natively — no external libraries or manual optimisation loops required.

Measure Sparklet's Memory Footprint on Your Hardware

Download the Sparklet evaluation binary and run it on your target MCU. The evaluation includes RAM and Flash usage reporting for your specific display resolution and widget set — concrete numbers before any licence commitment.