Reference·03
Troubleshooting
Common issues with generated code, simulation, and porting — and how to fix them.
Studio on desktop
The IDE feels slow, or I see "Software rendering active"
- Studio warns you when the GPU is unavailable and the UI falls back to software rendering (SwiftShader/llvmpipe). This is a driver/environment issue, not Studio itself.
- Linux + NVIDIA/Wayland: the most common cause. Update the driver, or try an X11 session. You can also launch with
--use-gl=eglor--use-angle=gl. - Virtual machines / remote desktop: GPU passthrough is often missing — enable 3D acceleration in the VM settings if available.
- Check what renderer is in use: open DevTools console and inspect
chrome://gpuin a Chromium-based browser for comparison, or look at the WebGL renderer string the warning shows. - Last resort: launch with
--disable-gpu— rendering stays on CPU but GPU init errors disappear.
Sign-in or any server request fails with "Failed to fetch"
- Check the system clock first. TLS certificate validation is strict: if the PC clock is behind the certificate's
notBefore(or pastnotAfter), every request toprotok.spacefails before it leaves the machine. Certificates are renewed regularly, so a clock that is even tens of minutes off can break the app while other software still works. Sync the clock (Windows: Settings → Time & Language → Sync now; Linux:timedatectl/ NTP) and restart Studio. - Corporate proxies, firewalls, and VPNs that intercept TLS can produce the same error — the app must reach
protok.space:443directly. - To see the exact network error, press
F12inside the app and check the DevTools console for anet::ERR_*code (e.g.ERR_CERT_DATE_INVALID,ERR_PROXY_CONNECTION_FAILED).
Generated code
Generated C does not compile on my target
- LVGL version mismatch. Protok targets LVGL 9.6.0. Older LVGL releases lack APIs the generated UI calls. Upgrade your LVGL.
- Missing runtime files. The generated code calls into the Protok runtime and LVGL. Make sure both are in your build and their include paths are set.
- Compiler not in C99 mode. The output is C99. Enable C99 (or later) in your toolchain.
- Stale generation. If you changed the project after generating, regenerate. The output is not patched in place.
Widget shows the wrong value or no value
- Check the signal binding in Studio — the signal must be bound to that widget's property.
- Check the DBC scaling (factor/offset) — the runtime applies it automatically; a wrong factor in the DBC means a wrong value on screen.
- Check the CAN ID and DLC match your DBC definition.
Simulation
The simulator shows a blank screen
- Make sure a screen is set as the active/load screen. The runtime loads the screen you marked for load on start.
- Check that assets (fonts/images) finished importing — a missing font can leave text invisible.
- Switch the canvas to Simulate mode; in Edit mode the preview is static.
Injected CAN frames do nothing
- Verify the frame ID matches a message in your imported DBC.
- Verify the DLC and byte layout match the signal definition.
- Confirm the signal is bound to a widget or logic input — unbound signals have no visible effect.
Logic nodes do not react to inputs
- Check that the node inputs are actually connected to a signal or widget — a floating input does nothing.
- Verify the node's condition/constants are set correctly in the inspector.
- Confirm the driving signal is arriving (check the CAN trace / injection).
Porting to my hardware
The UI renders but never updates
- Your LVGL display driver flush callback must call
lv_display_flush_ready()(or setflush_cbto signal completion) — otherwise LVGL stops refreshing. - Make sure
lv_tick_inc()is called every millisecond from a timer, andlv_timer_handler()runs in your main loop.
Touch input does not work
- Register an
lv_indev_tof typeLV_INDEV_TYPE_POINTERand feed touch coordinates in its read callback. - Call the read callback on each
lv_timer_handler()— LVGL polls it.
CAN frames are not received by the firmware
- Your CAN RX path must call
pli_can_sae1939_process_frame(bus, id, data, dlc)for every incoming frame — the generated code does not poll the bus. - Check CAN bitrate, filters, and transceiver wiring on the hardware side.
- Verify the frame ID matches a message in your DBC — unmatched IDs are ignored.
CAN TX does not reach the bus
- You must override the
pli_can_send_messageweak stub inpli_hal.c— the default stub does nothing. - Check that your CAN peripheral is initialized and the bus is in normal mode (not listen-only).
Hard fault / crash on startup
- Stack size: the generated code is static but LVGL and your drivers need stack headroom. Increase your task stack.
- Display framebuffer: make sure the LVGL draw buffer(s) are placed in accessible RAM (often non-cacheable or DMA-friendly).
- Initialization order: call
lv_init()and your display/input setup beforeui_init()andpli_can_init(). pli_get_tickreturning0forever (the weak stub) breaks all timing — override it with a real 1 ms tick source.
Simulator = ground truth
If a problem appears on hardware but not in the simulator, it is almost certainly in your HAL port (drivers, tick, stack, framebuffer) — not in the generated logic. The simulator runs the same runtime, so logic bugs show up there first.
Still stuck?
Reach out at contact@protok.tech with your project (or a minimal repro), the generated C, and your target details. We will help you get it running.
Where to go
- New here? Start with the quickstart.
- Porting? Read Runtime & HAL.
- What's in the output? See Generated code.