Embedded Linux app development guide — userspace vs kernel decisions, V4L2 camera drivers, VPU video pipelines, cross-compilation, systemd services, and OTA updates. Lessons from RK3128 boards, i.MX6Q video systems, and Raspberry Pi products.
Embedded Linux application development looks deceptively familiar: it is C/C++ or Python, it is POSIX, it compiles with GCC. Then the differences arrive all at once — you cross-compile for ARM, the root filesystem is 64 MB, the device has no package manager, the camera needs a kernel driver you have to write, and "reboot and see" takes three minutes per cycle. Teams coming from server or desktop Linux consistently underestimate the last mile between "runs on the dev board" and "ships as a product."
We have built Linux-based products on Rockchip, NXP i.MX, Allwinner, Raspberry Pi, and NVIDIA platforms — video codec systems, data acquisition terminals, camera drivers, control boards. This guide covers the decisions that matter: what lives in userspace vs. the kernel, how to handle video and cameras, and how to make a Linux device behave like a product instead of a science project.
The single most important architectural rule in embedded Linux: put as much as possible in userspace. Kernel code crashes the whole system, is miserable to debug, and complicates updates. Userspace code can be restarted, logged, and updated independently.
The Allwinner R528 control board for a laser cutter (laser_cutter) is a clean example of this discipline. Running Tina-Linux, it implements HTTP photo transfer, GCODE file reception and dispatch, WebSocket control, auto-start DHCP/HTTP/WebSocket services, and GPIO/UART/USB drivers — nearly all of it in userspace, talking to hardware through standard kernel interfaces. The application logic (job queueing, protocol handling, web services) never touches kernel code, which means it can be developed, tested, and updated like any server application.
Go to the kernel only when you must: a new hardware block with no existing driver, hard real-time requirements, or a performance-critical data path. Everything else belongs in userspace.
Video is where embedded Linux projects most often stall, because video is a pipeline problem and every stage can bottleneck.
On the capture side, the NVIDIA IMX568 camera driver project (nvidia_sensor) shows what kernel-side work looks like when it is unavoidable: sensor specifications, a v4l2_camera kernel module, and driver compilation delivering CSI camera acquisition through the standard V4L2 interface. Writing it against V4L2 instead of a proprietary API was the key decision — once the sensor appears as a standard V4L2 device, the entire Linux video ecosystem (GStreamer, V4L2 utilities, OpenCV) works with it unchanged.
On the processing side, the i.MX6Q video codec system (IMAX_VIDEO) uses the SoC's VPU for hardware video encoding and decoding, with Linux server-side code and sync deployment scripts. The lesson: never encode video on the ARM cores if the SoC has a VPU/GPU block. Software H.264 encoding of 1080p on a Cortex-A9 saturates the CPU and melts the power budget; the VPU does it at a fraction of the power. The application developer's job is plumbing — getting frames from V4L2 capture into the VPU encoder and out to the network — not writing codecs.
The pipeline mindset: capture (V4L2) → process (VPU/GPU or NEON-optimized userspace) → deliver (network/storage). Profile each stage independently. In our experience the bottleneck is rarely where you first guess.
Application developers inherit the BSP (board support package), but they should understand it — because BSP limitations become application limitations. The RK3128 Linux development board project (Linux3128) covers the full chain: Bootloader/U-Boot, kernel, and rootfs, with multiple Linux/Android firmware versions, MIPI-to-LVDS display driver board support, and Android flashing tools.
What application teams need from the BSP:
For the deep BSP bring-up story — DDR init, device trees, driver porting — see our companion guide to embedded Linux BSP bring-up.
Every embedded Linux project needs a reproducible build: same toolchain, same rootfs, same kernel, built by anyone, on any machine, producing bit-identical output. The options are Buildroot, Yocto, or a vendor SDK (like the RK312X/TRM documents and firmware toolchains in our RK3128 work). Our guidance:
Whatever you choose, the build runs in CI and produces versioned artifacts: kernel image, device tree, rootfs, and application packages. "It builds on my machine" is not a build system.
The gap between a demo and a product is all the unglamorous engineering:
Linux earns its keep on I/O-heavy applications. The i.MX6 CAN bus data acquisition system (imx6_can) concentrates its logic in a CanMain module handling multi-channel CAN data acquisition, parsing, and storage for automotive and industrial scenarios. On Linux, this kind of application gets SocketCAN (a proper network-stack-style API for CAN), real filesystems for storage, and scripting languages for the glue — capabilities that would each be a project on bare metal. When the application is fundamentally about moving and storing data, Linux is usually the right call.
Connected Linux devices get attacked — automatically, constantly, by bots scanning the entire internet. The baseline we apply to every product: unique per-device credentials (no shared default passwords, ever), a firewall allowing only required ports, automatic security updates for the OS layer separate from application updates, and encrypted storage for keys and personal data. Secure boot, where the hardware supports it, closes the loop by ensuring only signed firmware runs. None of this is exotic in 2026; shipping without it is negligence, and enterprise customers now ask for it in procurement checklists.
No matter how thorough the lab testing, the field will surprise you. The difference between a manageable surprise and a crisis is remote diagnostics designed in from the start. Every Linux device we ship includes: structured logging with severity levels (so the important messages are findable among the noise), a remote shell or management channel secured with per-device credentials (never a shared default password), and a "black box" recorder — a ring buffer in persistent storage capturing the last minutes of logs and system state before a crash or watchdog reset.
The black box recorder has paid for itself many times over. When a device in the field reboots at 2 AM, the question is never "did it reboot" but "what was it doing in the thirty seconds before." A ring buffer that survives the reboot answers that question; without it, you are guessing. Combined with remote log upload and the ability to push a diagnostic build OTA, most field issues become solvable from the office — which is the only economically sane way to support thousands of deployed devices.
Embedded Linux application development rewards teams that respect the platform's shape: userspace first, standard interfaces (V4L2, SocketCAN, libgpiod) over custom hacks, hardware video blocks over CPU encoding, reproducible builds, and the unglamorous product engineering — supervision, watchdogs, OTA — that turns a booting board into a shippable device.
If you are building a Linux-based product — video, data acquisition, control, or gateway — our Linux BSP development service covers the full stack from bootloader to application. Start with our BSP bring-up guide for the low-level story, and the IoT system architecture guide for how Linux devices fit into connected systems.
Contact us for customized solutions and quotes