Build

On a Chip — Firmware in C, the Screen as a Definition

By makemind · Feb 12, 2026

Chip companies don't only sell chips. Alongside the chip they ship an evaluation board — a small PCB they put in your hand saying "our chip can do this."

The moment you put a screen on that board, the job gets big. Add a graphics library, add fonts, attach a touch driver, lay out the UI, and burn all of it into flash. Move one button and burn it again. So most eval boards ship without a screen, and customers who need one go somewhere else.

This piece does it differently. No GUI goes on the board. Instead the board hands over two things — a list of what it can do, and a definition of the screen that shows it. The drawing happens outside.

Done for real on a WeAct STM32H723 on the desk.

What the board hands over

Attach over USB serial and ask, and it answers like this.

[serial] connected via serial_bridge /dev/cu.usbmodem365D395E33331 115200
[serial] tools: led.set, sys.info
[serial] resources: ui://app, ui://app/info, bundle://manifest.json

Two tools, three resources. That is the whole surface of this board.

The tools look like this.

{"tools":[
  {"name":"led.set","description":"Turn the on-board LED on or off",
   "inputSchema":{"type":"object","properties":{"on":{"type":"boolean"}},"required":["on"]}},
  {"name":"sys.info","description":"Report LED state and uptime",
   "inputSchema":{"type":"object","properties":{}}}]}

led.set and sys.info. This board can do plenty more — erase flash, change the clock, drop into the bootloader. Those capabilities are not on the list, and what is not on the list has no name to call.

The board holds the screen too

Read ui://app and the screen definition comes out.

[serial] ui://app — 656 B, type "page", title "WeAct H723 MCP Node"

656 bytes. That is what one screen costs. The client has not one line of UI code for this board — it receives and draws.

WeAct H723 MCP Node — the runtime drawing the definition the board handed over
WeAct H723 MCP Node — the runtime drawing the definition the board handed over

Press it and the board responds

The screen's button calls led.set. A real round trip.

[serial] led.set({"on":true})  -> "LED on"                      (1 ms)
[serial] sys.info({})          -> "LED=on uptime=205491208ms"   (10 ms)
[serial] led.set({"on":false}) -> "LED off"                     (10 ms)
[serial] sys.info({})          -> "LED=off uptime=205491232ms"  (11 ms)
[serial] uptime advanced 205491208 -> 205491232 ms

The LED on the board on the desk went on and off. And look at the last line — uptime advanced from 205491208 to 205491232, 24 milliseconds forward. That is not a canned answer; it is what the board was counting at that moment. A recorded response gives the same number when you ask twice.

Round trips are 1 to 11 milliseconds, because this is over UART.

The same client attaches to a different chip

That is what this structure is worth. The same code attached to an ESP32 across Wi-Fi.

[tcp] connected via tcp_bridge mcp-esp32.local 6270
[tcp] tools: led.set, sys.info
[tcp] ui://app — 158 B, type "application", title "ESP32 MCP Node"
[tcp] application — initialRoute "/" -> ui://page/main
[tcp] ui://page/main — 1894 B
[tcp] led.set({"on":true}) -> "LED on"  (89 ms)
[tcp] uptime advanced 67004328 -> 67004391 ms
ESP32 MCP Node — different vendor's chip, different transport, same client
ESP32 MCP Node — different vendor's chip, different transport, same client

Different vendor's chip, different transport, same client. The one thing that changed is which bridge program runs.

And the two boards' screens are structured differently. The STM32 hands over a single page (type: "page", 656 B); the ESP32 hands over an application with routes (type: "application", 158 B plus a 1894 B page). The board decides the shape of its own screen.

Latency differs. UART is 1–11 ms, Wi-Fi TCP is 17–89 ms. Different orders of magnitude, and that difference divides UI design — at single digits you can expect "press and it's done"; at tens of milliseconds you have to draw a waiting state.

This content requires Developer or above

Sign in and upgrade your plan to continue reading.

View Plans
Twitter