<?xml version="1.0" encoding="UTF-8"?>        <rss version="2.0"
             xmlns:atom="http://www.w3.org/2005/Atom"
             xmlns:dc="http://purl.org/dc/elements/1.1/"
             xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
             xmlns:admin="http://webns.net/mvcb/"
             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
             xmlns:content="http://purl.org/rss/1.0/modules/content/">
        <channel>
            <title>
									EDGEMTech Forum - Recent Topics				            </title>
            <link>https://edgemtech.ch/community/</link>
            <description>EDGEMTech Discussion Board</description>
            <language>en-US</language>
            <lastBuildDate>Thu, 09 Apr 2026 11:25:07 +0000</lastBuildDate>
            <generator>wpForo</generator>
            <ttl>60</ttl>
							                    <item>
                        <title>Yocto: The initramfs-framework</title>
                        <link>https://edgemtech.ch/community/general-discussions/yocto-the-initramfs-framework/</link>
                        <pubDate>Sun, 29 Mar 2026 08:48:27 +0000</pubDate>
                        <description><![CDATA[Introduction
When building embedded Linux systems with Yocto, there are situations where you need to run some code very early in the boot process, before the root filesystem is even mounted...]]></description>
                        <content:encoded><![CDATA[<h2>Introduction</h2>
<p class="font-claude-response-body break-words whitespace-normal leading-">When building embedded Linux systems with Yocto, there are situations where you need to run some code very early in the boot process, before the root filesystem is even mounted. This is exactly what the <strong>initramfs</strong> (initial RAM filesystem) is for: a temporary root filesystem loaded into memory by the bootloader, used to prepare the environment for the real root mount. Examples can be decrypting a partition, mounting a special device and so on.</p>
<p class="font-claude-response-body break-words whitespace-normal leading-">Yocto provides a useful framework to build and integrate an initramfs image directly into your distribution. In this post, we'll cover:</p>
<ul class=":mb-0 :mt-1 :gap-1 :pb-1 :pb-1 list-disc flex flex-col gap-1 pl-8 mb-3">
<li class="whitespace-normal break-words pl-2">How the initramfs framework works in Yocto</li>
<li class="whitespace-normal break-words pl-2">How to set it up in your layer</li>
<li class="whitespace-normal break-words pl-2">How to add a hook with a custom init script</li>
</ul>
<p class="font-claude-response-body break-words whitespace-normal leading-">Let's get into it.</p>
<h2> </h2>
<h2>Setup</h2>
<p class="font-claude-response-body break-words whitespace-normal leading-">The initramfs support in Yocto is built around a dedicated image recipe, typically based on <strong>core-image-minimal-initramfs</strong>, and a set of <strong>packagegroup</strong> recipes that bundle the necessary tools.</p>
<h3>Enabling the initramfs image</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">In your <strong>local.conf</strong> or distro configuration, add the following:</p>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span>INITRAMFS_IMAGE <span class="token token">=</span> <span class="token token">"core-image-minimal-initramfs"</span>
</span><span>INITRAMFS_IMAGE_BUNDLE <span class="token token">=</span> <span class="token token">"1"</span></span></code></pre>
</div>
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-"><strong>INITRAMFS_IMAGE</strong> tells Yocto which image recipe to use as the initramfs. Setting <strong>INITRAMFS_IMAGE_BUNDLE</strong> to <strong>"1"</strong> instructs the kernel build to bundle the initramfs cpio archive directly into the kernel image, so the bootloader only needs to load a single binary.</p>
<h3>The initramfs image recipe</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">The default <strong>core-image-minimal-initramfs</strong> recipe lives in <strong>meta/recipes-core/images/</strong>. It inherits <strong>core-image</strong> and pulls in a minimal package group:</p>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span class="token token"><span>PACKAGE_INSTALL </span>=<span> </span>"\
</span><span class="token token">    initramfs-framework \
</span><span class="token token">    base-passwd \
</span><span class="token token">    ${VIRTUAL-RUNTIME_base-utils} \
</span><span class="token token">"</span></code></pre>
</div>
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-">The key package here is <strong>initramfs-framework</strong>, which provides the modular init infrastructure we'll hook into.</p>
<h3>The initramfs-framework package</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-"><strong>initramfs-framework</strong> is a shell-based, modular init system designed specifically for Yocto initramfs images. It lives in <strong>meta/recipes-core/initrdscripts/</strong> and provides:</p>
<ul class=":mb-0 :mt-1 :gap-1 :pb-1 :pb-1 list-disc flex flex-col gap-1 pl-8 mb-3">
<li class="whitespace-normal break-words pl-2">A main <strong>/init</strong> script that sources modules in order</li>
<li class="whitespace-normal break-words pl-2">A set of built-in modules (e.g. <strong>udev</strong>, <strong>rootfs</strong>, <strong>nfsrootfs</strong>, ...)</li>
<li class="whitespace-normal break-words pl-2">A clean hook mechanism to add your own modules</li>
</ul>
<p class="font-claude-response-body break-words whitespace-normal leading-">Modules are shell scripts placed in <strong>/init.d/</strong> inside the initramfs, named with a numeric prefix to control execution order (e.g. <strong>00-debug</strong>, <strong>10-overlayroot</strong>).</p>
<h2> </h2>
<h2>Adding a Hook with a Custom Init Script</h2>
<p class="font-claude-response-body break-words whitespace-normal leading-">Now the interesting part. Say you need to run a custom script early in boot — for instance, to configure a network interface, check hardware, or set up an overlay. Here is how to do it cleanly using the <strong>initramfs-framework</strong> hook system.</p>
<h3>1. Write the module script</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">Create a shell script following the <strong>initramfs-framework</strong> module convention. Each module must define two functions:</p>
<ul class=":mb-0 :mt-1 :gap-1 :pb-1 :pb-1 list-disc flex flex-col gap-1 pl-8 mb-3">
<li class="whitespace-normal break-words pl-2"><strong>&lt;module&gt;_enabled</strong>: Determine if your module should run. Returning <strong>0</strong> means your module should run, returning <strong>1</strong> means it is deactivated.</li>
<li class="whitespace-normal break-words pl-2"><strong>&lt;module&gt;_run</strong>: Your custom module logic</li>
</ul>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="sticky opacity-0 group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 top-2 py-2 h-12 w-0 float-right">
<div class="absolute right-0 h-8 px-2 items-center inline-flex z-10">
<div class="relative"> </div>
</div>
</div>
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span><span class="token token shebang">#!/bin/sh</span>
</span><span><span class="token token"># modules/80-myhook</span>
</span><span>
</span><span><span class="token token">myhook_enabled</span><span class="token token">(</span><span class="token token">)</span> <span class="token token">{</span>
</span><span>    <span class="token token">return</span> <span class="token token">0</span>
</span><span><span class="token token">}</span>
</span><span>
</span><span><span class="token token">myhook_run</span><span class="token token">(</span><span class="token token">)</span> <span class="token token">{</span>
</span><span>    msg <span class="token token">"Running my custom initramfs hook..."</span>
</span><span>
</span><span>    <span class="token token"># Your logic here — e.g. load a kernel module, set up a mount, etc.</span>
</span><span>    modprobe mydriver
</span><span>
</span><span>    msg <span class="token token">"Custom hook done."</span>
</span><span><span class="token token">}</span></span></code></pre>
</div>
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-">The <strong>msg</strong> helper is provided by <strong>initramfs-framework</strong> and writes to the console. It also offers some other logging wrappers such as <strong>fatal</strong> and <strong>warn</strong>.</p>
<h3>2. Create a bbappend or new recipe</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">The cleanest way to integrate this into Yocto is to create a recipe in your custom layer that installs the module into the initramfs image.</p>
<p class="font-claude-response-body break-words whitespace-normal leading-">Create a recipe file, e.g. <strong>recipes-core/initrdscripts/initramfs-myhook_1.0.bb</strong>:</p>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span>SUMMARY <span class="token token">=</span> <span class="token token">"Custom initramfs hook for my project"</span>
</span><span>LICENSE <span class="token token">=</span> <span class="token token">"MIT"</span>
</span><span>LIC_FILES_CHKSUM <span class="token token">=</span> <span class="token token">"file://</span><span class="token token">${COMMON_LICENSE_DIR}</span><span class="token token">/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"</span>
</span><span>
</span><span>SRC_URI <span class="token token">=</span> <span class="token token">"file://80-myhook"</span>
</span><span>
</span><span>S <span class="token token">=</span> <span class="token token">"</span><span class="token token">${WORKDIR}</span><span class="token token">"</span>
</span><span>
</span><span><span class="token token">do_install</span><span class="token token">(</span><span class="token token">)</span> <span class="token token">{</span>
</span><span>    <span class="token token">install</span> -d <span class="token token">${D}</span>/init.d
</span><span>    <span class="token token">install</span> -m 0755 <span class="token token">${WORKDIR}</span>/80-myhook <span class="token token">${D}</span>/init.d/80-myhook
</span><span><span class="token token">}</span>
</span><span>
</span><span>FILES:<span class="token token">${PN}</span> <span class="token token">=</span> <span class="token token">"/init.d/80-myhook"</span></span></code></pre>
</div>
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-">Place your <strong>80-myhook</strong> script under <strong>recipes-core/initrdscripts/files/80-myhook</strong>.</p>
<h3>3. Add the package to your initramfs image</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">Either create a <strong>core-image-minimal-initramfs.bbappend</strong> in your layer, or create a custom initramfs image recipe. With the bbappend approach:</p>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span><span class="token token"># recipes-core/images/core-image-minimal-initramfs.bbappend</span>
</span><span>
</span><span>PACKAGE_INSTALL:append <span class="token token">=</span> <span class="token token">" initramfs-myhook"</span></span></code></pre>
</div>
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-">And just like that, the <strong>minimal-initramfs</strong> is extended with your init script. A custom recipe would allow more customization on <strong>core-image-minimal-initramfs</strong>, but for this use case, extending the existing recipe is enough.</p>
<h3>4. Build</h3>
<p class="font-claude-response-body break-words whitespace-normal leading-">Trigger the build as usual:</p>
<div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100" role="group" aria-label="Code bash">
<div class="overflow-x-auto">
<pre contenteditable="false"><code class="language-bash"><span>bitbake core-image-minimal-initramfs</span></code></pre>
</div>
</div>
<h2> </h2>
<h2>Conclusion</h2>
<p class="font-claude-response-body break-words whitespace-normal leading-">The <strong>initramfs-framework</strong> in Yocto provides a solid, modular foundation for early boot customization. Rather than hacking a monolithic <strong>init</strong> script, you can slot in well-isolated modules that are easy to maintain and test independently. The pattern is always the same: write a module script, package it in a recipe, add it to the initramfs image and Yocto takes care of the rest.</p>
<p class="font-claude-response-body break-words whitespace-normal leading-">This approach scales well as your project grows: need to add an <strong>overlayfs</strong> setup? A hardware self-test? An early network configuration? Each one becomes its own module with a clear numeric priority, living cleanly in your layer. It also bases itself on a well tested, actively maintained base.</p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>David Truan</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/general-discussions/yocto-the-initramfs-framework/</guid>
                    </item>
				                    <item>
                        <title>EDGEMTech and HEIG-VD Build an Open-Source Linux Virtualization Stack for Embedded LVGL-Based HMIs.</title>
                        <link>https://edgemtech.ch/community/orchestration-and-services/edgemtech-and-heig-vd-build-an-open-source-linux-virtualization-stack-for-portable-lvgl-based-hmis/</link>
                        <pubDate>Sun, 22 Mar 2026 14:19:50 +0000</pubDate>
                        <description><![CDATA[A joint collaboration in Yverdon-les-Bains on Linux, AVZ virtualization, SO3 capsules, and safety-oriented LVGL user interfaces.




EDGEMTech and HEIG-VD are jointly developing an open...]]></description>
                        <content:encoded><![CDATA[<table>
<tbody>
<tr>
<td width="624">
<p><span> <em>A joint collaboration in Yverdon-les-Bains on Linux, AVZ virtualization, SO3 capsules, and safety-oriented LVGL user interfaces.</em></span></p>
</td>
</tr>
</tbody>
</table>
<p><strong>EDGEMTech</strong><span> and <strong>HEIG-VD</strong> are jointly developing an <strong>open-source embedded software environment</strong> that combines <strong>Linux</strong>, the <strong>AVZ virtualization layer</strong>, and <strong>SO3 capsules</strong> to host modular graphical applications. The objective is to provide a robust execution platform for embedded products where hardware access, application isolation, portability, and long-term maintainability must coexist without compromising user-interface richness.</span></p>
<table>
<tbody>
<tr>
<td width="627">
<p><strong>Why this architecture matters</strong></p>
<p><strong>• </strong>Linux retains the critical services and direct hardware access.</p>
<p><strong>• </strong>Portainer can remotely orchestrate multiple SO3 capsules through a SO3-enabled agent running in the Linux domain.</p>
<p><strong>• </strong>Each capsule can host a dedicated LVGL-based application, enabling clean separation between product modes or customer-specific HMIs.</p>
<p><strong>• </strong>A split graphics architecture isolates application logic from low-level rendering details, improving portability across platforms and display stacks.</p>
<p><strong>• </strong>LVGL Safe can be combined with capsule isolation for safety-oriented HMI designs.</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><img style="float: left;margin-left: auto;margin-right: auto" src="https://edgemtech.ch/wp-content/uploads/wpforo/default_attachments/1774191600-20260322_MICOFE_LVGL.png" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Figure 1. </strong><em>High-level view of the software stack: Portainer-driven orchestration in Linux, multiple SO3 capsules hosting LVGL applications, and display front-end/back-end separation over the AVZ hypervisor.</em></p>
<ol>
<li><strong> Architecture overview</strong></li>
</ol>
<p><span>At the bottom of the stack, the AVZ hypervisor provides the virtualization layer used to partition the execution environment. Above it, the Linux domain remains the system anchor point: it hosts the services that need direct access to the physical hardware, keeps ownership of the low-level graphics drivers, and exposes the execution and orchestration services required to manage isolated application domains.</span></p>
<p><span>On top of this base, SO3 capsules can be instantiated as strongly isolated execution contexts dedicated to user-interface workloads. The diagram illustrates capsules hosting graphical applications written in C, C++, micro-Python and soon Rust, but the same model can be extended to other language bindings when relevant. Each capsule packages its own application logic together with the LVGL user-interface stack and the required runtime components.</span></p>
<ol start="2">
<li><strong> Portainer orchestration and capsule lifecycle</strong></li>
</ol>
<p><span>A key part of the approach is the integration of Portainer for orchestration. A Portainer manager communicates with a SO3-enabled agent running in the Linux domain. This agent acts as the control bridge between the orchestration layer and the embedded virtualization environment.</span></p>
<p><span>From an operational standpoint, this makes it possible to deploy, update, stop, and supervise several capsules on the same target. Instead of embedding all graphical functions inside a single monolithic application, different LVGL-based apps can be packaged into separate capsules and managed independently. This is especially attractive for products that need distinct operating modes, customer-specific HMIs, service interfaces, or staged feature rollouts.</span></p>
<p><span>The same mechanism also opens the door to switching between capsules according to the active application context. In practice, one capsule can implement one HMI profile while another capsule implements a different one, with the orchestrator selecting which capsule is currently active or visible. This preserves a clean separation between applications while simplifying update strategies and fault containment.</span></p>
<ol start="3">
<li><strong> Split graphics architecture and LVGL portability</strong></li>
</ol>
<p><span>One of the most interesting technical aspects of the architecture is the split between user-interface logic and graphics implementation. The LVGL application and its UI logic run inside the capsule, while the hardware-facing graphics components remain anchored in the Linux domain.</span></p>
<p><span>In the diagram, this split appears through the distinction between the display front-end driver on the capsule side and the display back-end driver on the Linux side, the latter itself relying on the native graphics stack and drivers such as DRM, framebuffer, or other platform-specific implementations. This separation keeps the application layer focused on UI behavior, widgets, layouts, and event handling, while the rendering and display integration can be adapted independently to the target hardware.</span></p>
<p><span>This design greatly improves portability. An LVGL application can be kept largely unchanged while the graphics back-end is retargeted to another SoC, another display controller, or another rendering path. The same UI logic can therefore be reused across product families with fewer modifications in the high-level application code. In other words, portability is obtained not by freezing the whole stack, but by isolating the platform-dependent layers where they belong.</span></p>
<ol start="4">
<li><strong> LVGL Pro workflow and LVGL Safe perspective</strong></li>
</ol>
<p><span>The workflow can also benefit from the LVGL Pro editor, which provides a practical way to design the user interface and generate the corresponding target code. In this architecture, the generated application can then be packaged into a capsule and deployed through the orchestration layer, preserving a consistent pipeline from UI design to embedded deployment.</span></p>
<p><span>The safety-oriented dimension is equally important. LVGL Safe is highly relevant in this context because it complements the architectural isolation already provided by capsules and virtualization. When a UI is placed inside a strongly partitioned execution environment, and when its graphics path is explicitly controlled through front-end/back-end separation, LVGL Safe becomes an especially compelling candidate for applications that have stronger safety, robustness, or certification-driven requirements.</span></p>
<p><span>The combination of LVGL Safe and SO3 capsules therefore offers a promising route for highly critical environments in which a graphical interface is still required, but where fault containment, software partitioning, controlled updates, and predictable system behavior are mandatory design constraints.</span></p>
<ol start="5">
<li><strong> Open-source engineering collaboration</strong></li>
</ol>
<p><span>Beyond the technical stack itself, this project also reflects the value of a close collaboration between industrial engineering and applied research. EDGEMTech brings product-oriented embedded software expertise, customer-facing constraints, and deployment pragmatism, while HEIG-VD contributes engineering depth, experimentation capacity, and a strong academic environment to structure and validate the approach.</span></p>
<p><span>Together, the goal is to consolidate a reusable open-source foundation for Linux-based virtualized embedded systems, capable of hosting advanced and portable HMIs with a clean separation of concerns between orchestration, application logic, and hardware-specific graphics integration.</span></p>
<p><span>We are currently preparing several showcases based on Raspberry Pi 4 platforms to illustrate this architecture in practice. More demonstrations and technical details will be shared soon.</span></p>
<p><em>This article is intended as a technical introduction to the ongoing collaboration. More implementation details, demonstrations, and feedback from field deployments will be shared as the project evolves.</em></p>
<p><em> </em></p>
<p><span> </span></p>
<div id="wpfa-2784" class="wpforo-attached-file"><a class="wpforo-default-attachment" title="20260322_MICOFE_LVGL.png" href="//edgemtech.ch/wp-content/uploads/wpforo/default_attachments/1774191600-20260322_MICOFE_LVGL.png" target="_blank" rel="noopener"><i class="fas fa-paperclip"></i> 20260322_MICOFE_LVGL.png</a></div>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Daniel Rossier</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/orchestration-and-services/edgemtech-and-heig-vd-build-an-open-source-linux-virtualization-stack-for-portable-lvgl-based-hmis/</guid>
                    </item>
				                    <item>
                        <title>RTTarget-32</title>
                        <link>https://edgemtech.ch/community/realtime-systems/rttarget-32/</link>
                        <pubDate>Sun, 15 Mar 2026 12:03:21 +0000</pubDate>
                        <description><![CDATA[Recently, we&#039;ve been contracted to add support for the Intel Atom X6000E platform to an RTOS called RTTargetthe company that provided RTTarget, On-Time Informatik GmbH has ceased operations ...]]></description>
                        <content:encoded><![CDATA[<p>Recently, we've been contracted to add support for the Intel Atom X6000E platform to an RTOS called RTTarget <a href="http://www.on-time.com/rttarget-32.htm" target="_blank" rel="noopener">http://www.on-time.com/rttarget-32.htm</a><br /><br />Unfortunately, the company that provided RTTarget, On-Time Informatik GmbH has ceased operations back in 2022. But a lot of companies still use it. The RTOS implements the Win32 library allowing to run Windows applications on embedded x86 based platforms. After running them through a special tool that does fixups on .exe files.<br /><br />Our primary goal was add support for the network adapter provided by the X6000E which uses IP blocks from Synopsis. I've decided to use the dwqe driver from OpenBSD, because all other network drivers that RTTarget supports were taken from BSD variants.. It was not easy due to lack of information and only brief documentation online about this Ethernet controller. In the end, we were able to achieve the desired result, it was perhaps one of the hardest challenges that I've achieved in my career until now and I've learned a great lot about Ethernet controllers and PHYs in process.<br /><br />A lot of parts of RTTarget are written in pure x86 assembly using Borland Turbo Assembler (TASM), so I had to get back into the internals of the x86 architecture.<br /><br />I did enjoy doing instruction level debugging in QEMU to diagnose early boot problems when using the UEFI mode. Rttarget can boot on 64-bit boot systems because the EFI loader provided by On-Time switches the processor from long mode (x86-64) back into regular protected mode (x86) before calling the boot vector of RTTarget-32.<br /><br />I also enjoyed this project because it made me work with another compiler. Using something else instead of the usual GCC or LLVM clang is very rare nowadays... Borland C++ 5.5.1 provides very terse error messages that oblige the programmer to search for the error. GCC is way more helpful in this regard, pointing the exact cause and location of the error. C is also a language that supports many different styles, Rttarget-32 follows usual Windows conventions. That is heavy uses of typedefs and even lower case macros. But hey, it's still C, I can figure this out...<br /><br /></p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Erik Tagirov</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/realtime-systems/rttarget-32/</guid>
                    </item>
				                    <item>
                        <title>EDGEMTech at Embedded World 2026</title>
                        <link>https://edgemtech.ch/community/general-discussions/edgemtech-at-embedded-world-2026/</link>
                        <pubDate>Sun, 22 Feb 2026 14:53:31 +0000</pubDate>
                        <description><![CDATA[&#x1f680; EDGEMTech at Embedded World 2026
We’re excited to announce that EDGEMTech SA will be attending Embedded World 2026 in Nuremberg on March 10-11.
Embedded World is one of the most ...]]></description>
                        <content:encoded><![CDATA[<h2>&#x1f680; EDGEMTech at Embedded World 2026</h2>
<p data-start="212" data-end="330">We’re excited to announce that <strong data-start="243" data-end="259">EDGEMTech SA</strong> will be attending <strong data-start="278" data-end="301">Embedded World 2026</strong> in Nuremberg on March 10-11.</p>
<p data-start="332" data-end="732">Embedded World is one of the most important international gatherings for the embedded systems community. The event brings together experts in embedded hardware, firmware, software platforms, IoT, connectivity, HMI/GUI technologies, and system architecture. It’s always a great opportunity to explore the latest innovations, exchange ideas, and connect with industry leaders from across the ecosystem.</p>
<h3>&#x1f3af; Why we’re attending</h3>
<p data-start="762" data-end="790">This year, our goals are to:</p>
<ul data-start="792" data-end="1081">
<li data-start="792" data-end="843">
<p data-start="794" data-end="843">Strengthen relationships with existing partners</p>
</li>
<li data-start="844" data-end="908">
<p data-start="846" data-end="908">Meet new companies working in embedded and connected systems</p>
</li>
<li data-start="909" data-end="954">
<p data-start="911" data-end="954">Explore emerging technologies and tooling</p>
</li>
<li data-start="955" data-end="1016">
<p data-start="957" data-end="1016">Discuss upcoming projects and collaboration opportunities</p>
</li>
<li data-start="1017" data-end="1081">
<p data-start="1019" data-end="1081">Stay closely aligned with industry trends and best practices</p>
</li>
</ul>
<p data-start="1083" data-end="1200">Although we won’t have a booth this year, our team will be present at the event and visiting several of our partners.</p>
<p data-start="1202" data-end="1490">We’re also happy to share that our close partner <strong data-start="1251" data-end="1292"><span class="hover:entity-accent entity-underline inline cursor-pointer align-baseline"><span class="whitespace-normal">LVGL</span></span></strong> will be attending and exhibiting at Embedded World. As many of you know, LVGL plays a key role in modern embedded GUI development, and we look forward to connecting with their team on-site as well.</p>
<h3>&#x1f91d; Let’s connect in Nuremberg</h3>
<p data-start="1527" data-end="1655">If you’re attending Embedded World and would like to meet, we’d be delighted to connect in person. Whether you’re interested in:</p>
<ul data-start="1657" data-end="1829">
<li data-start="1657" data-end="1690">
<p data-start="1659" data-end="1690">Embedded firmware development</p>
</li>
<li data-start="1691" data-end="1716">
<p data-start="1693" data-end="1716">GUI and HMI solutions</p>
</li>
<li data-start="1717" data-end="1757">
<p data-start="1719" data-end="1757">System architecture and optimization</p>
</li>
<li data-start="1758" data-end="1789">
<p data-start="1760" data-end="1789">Product development support</p>
</li>
<li data-start="1790" data-end="1829">
<p data-start="1792" data-end="1829">Or exploring potential partnerships</p>
</li>
</ul>
<p data-start="1831" data-end="1899">Feel free to reach out and schedule a time to meet during the event.</p>
<p data-start="1901" data-end="1920">You can contact us:</p>
<ul data-start="1921" data-end="2003">
<li data-start="1921" data-end="1961">
<p data-start="1923" data-end="1961">Via direct message here on the forum</p>
</li>
<li data-start="1962" data-end="2003">
<p data-start="1964" data-end="2003">Or through our usual contact channels</p>
</li>
</ul>
<p data-start="2005" data-end="2121">We’re looking forward to a productive and inspiring few days in Nuremberg... and hopefully meeting some of you there!</p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Gabriel CATEL TORRES</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/general-discussions/edgemtech-at-embedded-world-2026/</guid>
                    </item>
				                    <item>
                        <title>Torizon VSCode extension: What are those Dockerfile?</title>
                        <link>https://edgemtech.ch/community/orchestration-and-services/torizon-vscode-extension-what-are-those-dockerfile/</link>
                        <pubDate>Sun, 15 Feb 2026 07:36:00 +0000</pubDate>
                        <description><![CDATA[Understanding the Dockerfiles in the Torizon VS Code Templates
Hello everyone! 
Following the article about Torizon VSCode Extension by my colleague Gabriel, I wanted to add a bit more exp...]]></description>
                        <content:encoded><![CDATA[<h1>Understanding the Dockerfiles in the Torizon VS Code Templates</h1>
<p>Hello everyone! </p>
<p>Following <a href="https://edgemtech.ch/community/orchestration-and-services/torizon-vs-code-ide-extension/#post-26" target="_blank" rel="noopener">the article about Torizon VSCode Extension</a> by my colleague Gabriel, I wanted to add a bit more explanation about how to effectively use it.</p>
<p>If you're getting started with the <a href="https://github.com/torizon/vscode-torizon-templates">Torizon IDE Extension</a> and wondering why your project has three Dockerfiles and a docker-compose file, this quick guide is for you. I'll use the <strong>cLvgl</strong> template as an example, but the same pattern applies to most C/C++ Torizon templates.</p>
<h2>Overview</h2>
<p>Every Torizon IDE C/C++ template includes these container-related files:</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Purpose</th>
<th>"Runs" on</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Dockerfile</code></td>
<td>Production image (multi-stage: build + deploy)</td>
<td>Target device</td>
</tr>
<tr>
<td><code>Dockerfile.debug</code></td>
<td>Debug image with SSH &amp; GDB</td>
<td>Target device</td>
</tr>
<tr>
<td><code>Dockerfile.sdk</code></td>
<td>Cross-compilation toolchain</td>
<td>Host machine</td>
</tr>
<tr>
<td><code>docker-compose.yml</code></td>
<td>Orchestrates debug and release services</td>
<td>Target device</td>
</tr>
</tbody>
</table>
<p>Let's walk through each one.</p>
<h2> </h2>
<h2><code>Dockerfile:</code> Production Image</h2>
<p>This is a <strong>multi-stage</strong> Dockerfile that both compiles and packages your app for production.</p>
<p><strong>Stage 1 — <code>build</code>:</strong> Uses <code>torizon/cross-toolchain-${IMAGE_ARCH}</code> as a base. It installs <code>cmake</code>, copies your source code, and cross-compiles the application for your target architecture (arm64, armhf, etc.) in Release mode.</p>
<p><strong>Stage 2 — <code>deploy</code>:</strong> Starts from a minimal <code>torizon/debian</code> image for the target platform. It copies <em>only</em> the compiled binary from the build stage (<code>build-${IMAGE_ARCH}/bin</code>) into the container. The final image is clean — no compiler, no build tools, just your app.</p>
<p>The entrypoint is simply:</p>
<pre contenteditable="false"><code class="language-dockerfile">CMD 
</code></pre>
<p>This is the image you'll push to a registry and deploy to your devices in the field.</p>
<p>&nbsp;</p>
<h2><code>Dockerfile.debug:</code> Development/Debug Image</h2>
<p>This Dockerfile builds a container specifically for <strong>remote debugging</strong> during development. Unlike the production Dockerfile, it does <strong>not</strong> compile your code. Instead it:</p>
<ol>
<li>Starts from the same <code>torizon/debian</code> base image for the target platform.</li>
<li>Installs debug tooling: <code>openssh-server</code>, <code>gdb</code>, <code>rsync</code>, <code>curl</code>, and <code>file</code>.</li>
<li>Configures an SSH server on a custom port (<code>DEBUG_SSH_PORT</code>) so VS Code can connect via Pipe Transport and attach the debugger.</li>
</ol>
<p>The SSH setup is intentionally insecure (empty password, root login permitted) — this is fine for a development container, but obviously not something you'd ship.</p>
<p>Notice that there's no <code>COPY</code> of source or build artifacts in this file. During the debug workflow, the IDE Extension's tasks handle copying the compiled output (built by the SDK container) into this container at deploy time. The container's only job at runtime is to run the SSH daemon:</p>
<pre contenteditable="false"><code class="language-dockerfile">CMD 
</code></pre>
<p>VS Code then connects over SSH, uploads the binary, and attaches GDB.</p>
<h2> </h2>
<h2><code>Dockerfile.sdk: </code>Cross-Compilation Toolchain</h2>
<p>This Dockerfile creates the <strong>SDK container</strong> — the environment where your code gets cross-compiled during development.</p>
<p>It's based on <code>torizon/cross-toolchain-${IMAGE_ARCH}</code> and installs <code>cmake</code> plus any additional build dependencies you need. The key thing is how it's used: the Torizon IDE Extension runs this container on your <strong>host machine</strong> with your project workspace <strong>bind-mounted</strong> into it:</p>
<pre contenteditable="false"><code>-v ${workspaceFolder}:${APP_ROOT}
</code></pre>
<p>This means:</p>
<ul>
<li>The SDK container has access to your source code.</li>
<li>Build outputs land directly in your workspace (e.g., <code>build-arm64/</code>).</li>
<li>Incremental builds work — artifacts persist between sessions.</li>
<li>The container runs as user <code>torizon</code> (not root).</li>
</ul>
<p>You only need this file for compiled languages. Templates for interpreted languages (Python, Node.js, etc.) won't have a <code>Dockerfile.sdk</code>.</p>
<h2> </h2>
<h2><code>docker-compose.yml: Making it run!</code></h2>
<p>The compose file defines <strong>two services</strong>, separated by profiles:</p>
<h3><code>__container__-debug</code> (profile: <code>debug</code>)</h3>
<p>This service uses <code>Dockerfile.debug</code>. It:</p>
<ul>
<li>Forwards the <code>DEBUG_SSH_PORT</code> so VS Code can connect.</li>
<li>Grants access to device nodes (<code>/dev</code>) via a bind mount and cgroup rules for tty, input devices, DRI (GPU), and framebuffer — essential for an LVGL app that needs to render to a display.</li>
<li>Is only started when the <code>debug</code> profile is active.</li>
</ul>
<h3><code>__container__</code> (profile: <code>release</code>)</h3>
<p>This service uses the production <code>Dockerfile</code>. It has the same device access and volume configuration as the debug service, but no SSH port forwarding. The image tag uses <code>${DOCKER_LOGIN}</code> instead of <code>${LOCAL_REGISTRY}</code>, meaning it's intended to be pushed to a remote registry.</p>
<p>The <code>__container__</code> placeholder gets replaced with your actual project name when you create a project from the template.</p>
<h3>How the profiles work</h3>
<p>The Torizon IDE Extension activates the appropriate profile automatically:</p>
<ul>
<li>During development/debugging → <code>docker compose --profile debug up</code></li>
<li>For production/release testing → <code>docker compose --profile release up</code></li>
</ul>
<p>This means both services are defined in the same file but never run simultaneously.</p>
<h2> </h2>
<h2>Wrap up: How They Work Together</h2>
<p>Here's how the three Dockerfiles fit into the development workflow:</p>
<ol>
<li>You write code on your host machine.</li>
<li><code><strong>Dockerfile.sdk</strong></code> → The IDE Extension builds the SDK container and runs <code>cmake</code> inside it (with your workspace bind-mounted) to cross-compile your code.</li>
<li><strong><code>Dockerfile.debug</code> </strong>→ The IDE Extension builds the debug container, deploys it to the target device, copies the compiled binary into it, and VS Code attaches GDB over SSH.</li>
<li><strong><code>Dockerfile</code></strong> → When you're ready to release, this multi-stage Dockerfile compiles and packages everything into a minimal production image.</li>
</ol>
<h2> </h2>
<h2>Adding Custom Dependencies</h2>
<p>You'll notice special labels like <code>__torizon_packages_build_start__</code> and <code>__torizon_packages_prod_start__</code> in the Dockerfiles. The IDE Extension uses these markers to automatically inject packages you configure via <code>torizonPackages.json</code>. You can also add packages manually between those labels.</p>
<p>&nbsp;</p>
<h2>Conclusion</h2>
<p>Hopefully this clears up the role of each file in those templates! The Torizon IDE Extension handles most of the orchestration for you, but understanding what each Dockerfile does helps a lot when you need to customize your build or debug a deployment issue!</p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>David Truan</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/orchestration-and-services/torizon-vscode-extension-what-are-those-dockerfile/</guid>
                    </item>
				                    <item>
                        <title>SO3: A Small Operating System with Big Low-Level Ambitions</title>
                        <link>https://edgemtech.ch/community/general-discussions/so3-a-small-operating-system-with-big-low-level-ambitions/</link>
                        <pubDate>Sun, 08 Feb 2026 17:30:07 +0000</pubDate>
                        <description><![CDATA[When I started developing SO3 in 2014, I never imagined it would live beyond an academic setting. At the time, it was primarily a learning and experimentation platform—a way to explore how o...]]></description>
                        <content:encoded><![CDATA[<p data-start="314" data-end="592">When I started developing <strong data-start="340" data-end="347">SO3 </strong>in 2014, I never imagined it would live beyond an academic setting. At the time, it was primarily a learning and experimentation platform—a way to explore how operating systems really work, from the CPU up to the abstractions we often take for granted.</p>
<p data-start="594" data-end="699">Today, SO3 is an open-source project available on GitHub:</p>
<p data-start="594" data-end="699">&#x1f449; <a class="decorated-link" href="https://github.com/smartobjectoriented/so3" target="_new" rel="noopener" data-start="657" data-end="699">https://github.com/smartobjectoriented/so3<span class="ms-0.5 inline-block align-middle leading-none" aria-hidden="true"></span></a></p>
<p data-start="701" data-end="1106">SO3 is <strong data-start="708" data-end="715">not</strong> meant to compete with production-grade embedded operating systems like FreeRTOS or Zephyr. Those systems are designed to be dropped into countless real-world products. SO3 has a different goal: it is deliberately focused on <strong data-start="940" data-end="962">deep understanding</strong>. It is built for exploring low-level interactions with the CPU, memory subsystem, and peripherals, with as little conceptual noise as possible.</p>
<h2>Minimal Code, Real OS Concepts</h2>
<p data-start="1144" data-end="1263">Despite its small codebase, SO3 implements most of the core mechanisms you would expect from a modern operating system:</p>
<ul data-start="1265" data-end="1394">
<li data-start="1265" data-end="1322">
<p data-start="1267" data-end="1322">strict separation between user space and kernel space</p>
</li>
<li data-start="1323" data-end="1352">
<p data-start="1325" data-end="1352">virtual memory management</p>
</li>
<li data-start="1353" data-end="1394">
<p data-start="1355" data-end="1394">support for running as a <strong data-start="1380" data-end="1394">hypervisor</strong></p>
</li>
</ul>
<p data-start="1396" data-end="1534">This minimal surface is intentional. SO3 aims to expose <em data-start="1452" data-end="1457">how</em> these mechanisms work rather than hide them behind layers of framework code.</p>
<h2>AVZ, Capsules, and Coexisting with Linux</h2>
<p data-start="1582" data-end="1790">When SO3 runs as a hypervisor, it takes the name <strong data-start="1631" data-end="1638">AVZ</strong> (Agency Virtualizer)—a name inherited from earlier stages of the project. In this configuration, AVZ can host Linux, but that’s only part of the story.</p>
<p data-start="1792" data-end="2044">What makes AVZ particularly interesting is that <strong data-start="1840" data-end="1878">SO3 itself can run alongside Linux</strong>, at the same time, on the same hardware. Multiple SO3 instances can coexist simultaneously, each running in a fully memory-isolated environment called a <strong data-start="2032" data-end="2043">capsule</strong>.</p>
<p data-start="2046" data-end="2272">These capsules provide strong isolation guarantees and open the door to experimentation with secure execution environments, partitioning, and mixed-criticality systems—all without the complexity of a large hypervisor codebase.</p>
<h2>Modern Tooling, Familiar Interfaces</h2>
<p data-start="2315" data-end="2376">Over time, SO3 has grown beyond its early experimental roots:</p>
<ul data-start="2378" data-end="2527">
<li data-start="2378" data-end="2445">
<p data-start="2380" data-end="2445">It is now fully compatible with the <strong data-start="2416" data-end="2424">musl</strong> C standard library</p>
</li>
<li data-start="2446" data-end="2527">
<p data-start="2448" data-end="2527">Its networking capabilities are built on the well-known <strong data-start="2504" data-end="2512">lwIP</strong> TCP/IP stack</p>
</li>
</ul>
<p data-start="2529" data-end="2626">This makes it possible to write real applications for SO3 while still staying close to the metal.</p>
<h3>Used in Real Projects: LVGL Continuous Integration</h3>
<p data-start="2684" data-end="2947">While SO3 remains focused on education and experimentation, it has also found practical use in real-world workflows. Notably, <strong data-start="2810" data-end="2875">SO3 is used in the LVGL continuous integration infrastructure</strong> to execute non-regression tests on the LVGL codebase.</p>
<p data-start="2949" data-end="3129">In this context, SO3 provides a controlled and deterministic execution environment, making it particularly well-suited for automated testing of low-level and graphics-related code.</p>
<h2>Where SO3 Runs Today</h2>
<p data-start="3157" data-end="3179">SO3 currently runs on:</p>
<ul data-start="3181" data-end="3251">
<li data-start="3181" data-end="3223">
<p data-start="3183" data-end="3223">QEMU ARM platforms (32-bit and 64-bit)</p>
</li>
<li data-start="3224" data-end="3251">
<p data-start="3226" data-end="3251">The Raspberry Pi family</p>
</li>
</ul>
<p data-start="3253" data-end="3362">This makes it accessible both for fast experimentation in emulation and for hands-on work with real hardware.</p>
<h2>A Learning Tool First—and Proud of It</h2>
<ul>
<li data-start="3407" data-end="3695">SO3 is not about being everything to everyone. It is about clarity, control, and understanding. Whether you are curious about operating system internals, virtualization, or low-level ARM platforms, SO3 offers a compact and honest environment where nothing is too abstracted to learn from.</li>
</ul>
<p data-start="3697" data-end="3756">In short: <strong data-start="3707" data-end="3756">SO3 is small by design—but it goes very deep.</strong></p>
<p data-start="3697" data-end="3756"> </p>
<ul>
<li data-start="3697" data-end="3756">https://github.com/smartobjectoriented/so3</li>
<li data-start="3697" data-end="3756"><a href="https://www.nongnu.org/lwip/2_1_x/index.html">https://www.nongnu.org/lwip/2_1_x/index.htm</a></li>
<li data-start="3697" data-end="3756">https://musl.libc.org/</li>
<li data-start="3697" data-end="3756">https://lvgl.io</li>
</ul>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Daniel Rossier</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/general-discussions/so3-a-small-operating-system-with-big-low-level-ambitions/</guid>
                    </item>
				                    <item>
                        <title>Rendering QR Codes in LVGL: From Pixels to Philosophy</title>
                        <link>https://edgemtech.ch/community/embedded-user-interface/rendering-qr-codes-in-lvgl-from-pixels-to-philosophy/</link>
                        <pubDate>Sat, 10 Jan 2026 10:07:37 +0000</pubDate>
                        <description><![CDATA[QR codes have become a ubiquitous way to encode and share information, URLs, contact details, configuration parameters, and more. With LVGL, embedding a QR code into your embedded UI is stra...]]></description>
                        <content:encoded><![CDATA[<p><!-- wp:paragraph --></p>
<p id="viewer-n5y3u1052">QR codes have become a ubiquitous way to encode and share information, URLs, contact details, configuration parameters, and more. With LVGL, embedding a QR code into your embedded UI is straightforward. In this post, we’ll explore how to use QR codes in LVGL, discuss the limits of QR code sizing on embedded displays, and take a step back to reflect on the design philosophy behind these clever square patterns.</p>
<p><!-- /wp:paragraph -->

<!-- wp:heading --></p>
<h3 id="viewer-u8hr41193" class="wp-block-heading">Using QR Codes in LVGL</h3>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-btrzq1202">Starting from LVGL v8, the library includes a built-in widget for generating and displaying QR codes.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-6g1az1815">Here's a simple example:</p>
<p><!-- /wp:paragraph -->

<!-- wp:kevinbatdorf/code-block-pro --></p>
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono"><span></span>
<pre class="code-block-pro-copy-button-pre" contenteditable="false" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" readonly="readonly" aria-hidden="true">int main(lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 100, lv_color_black(), lv_color_white());
lv_qrcode_update(qr, "https://www.edgemtech.com");) {
  return 0;
}

lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 100, lv_color_black(), lv_color_white());
lv_qrcode_update(qr, "https://www.edgemtech.com");
}</textarea></pre>
<pre class="shiki nord" contenteditable="false"><code><span class="line"><span>int</span><span> </span><span>main</span><span>(</span><span>lv_obj_t</span><span> </span><span>*</span><span> </span><span>qr</span><span> </span><span>=</span><span> </span><span>lv_qrcode_create</span><span>(</span><span>lv_scr_act</span><span>()</span><span>,</span><span> </span><span>100</span><span>,</span><span> </span><span>lv_color_black</span><span>()</span><span>,</span><span> </span><span>lv_color_white</span><span>());</span></span>
<span class="line"><span>lv_qrcode_update</span><span>(</span><span>qr</span><span>,</span><span> </span><span>"</span><span>https://www.edgemtech.com</span><span>"</span><span>);) </span><span>{</span></span>
<span class="line"><span>  </span><span>return</span><span> </span><span>0</span><span>;</span></span>
<span class="line"><span>}</span></span>
<span class="line"></span>
<span class="line"><span>lv_obj_t</span><span> </span><span>*</span><span> </span><span>qr</span><span> </span><span>=</span><span> </span><span>lv_qrcode_create</span><span>(</span><span>lv_scr_act</span><span>()</span><span>,</span><span> </span><span>100</span><span>,</span><span> </span><span>lv_color_black</span><span>()</span><span>,</span><span> </span><span>lv_color_white</span><span>())</span><span>;</span></span>
<span class="line"><span>lv_qrcode_update</span><span>(</span><span>qr</span><span>,</span><span> </span><span>"</span><span>https://www.edgemtech.com</span><span>"</span><span>)</span><span>;</span></span>
<span class="line"><span>}</span></span></code></pre>
</div>
<p><!-- /wp:kevinbatdorf/code-block-pro -->

<!-- wp:paragraph --></p>
<p id="viewer-kvzjt1863">This snippet creates a 100x100 pixel QR code in black on a white background. The <strong>lv_qrcode_update</strong> function encodes the string into the QR pattern.</p>
<p><!-- /wp:paragraph -->

<!-- wp:heading --></p>
<h3 id="viewer-fpcoa2070" class="wp-block-heading">Display Limitations and Scaling</h3>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-xxmt52100">The size of your QR code is constrained by:</p>
<p><!-- /wp:paragraph -->

<!-- wp:list --></p>
<ul class="wp-block-list"><!-- wp:list-item -->
<li>The screen resolution</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>The desired readability (especially when using a camera)</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>The error correction level and data complexity</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list -->

<!-- wp:paragraph --></p>
<p id="viewer-8n2wv2112">LVGL supports scaling the QR pattern with pixel-perfect precision. However, embedded displays often have limited resolution. For example, on a 128x128 screen, you might only fit a version 2 QR code (~25x25 modules) cleanly, assuming each module is 4-5 pixels.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-9op822114">&#x26a0;&#xfe0f; <strong>Rule of thumb:</strong> Always scale each module (square) to at least 3x3 pixels for reliable scanning.</p>
<p><!-- /wp:paragraph -->

<!-- wp:heading --></p>
<h3 id="viewer-5l7y72552" class="wp-block-heading">A Word on QR Code Structure</h3>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-b5nih2609">QR codes are built using a defined standard (ISO/IEC 18004), consisting of:</p>
<p><!-- /wp:paragraph -->

<!-- wp:list --></p>
<ul class="wp-block-list"><!-- wp:list-item -->
<li><strong>Finder patterns</strong>: the large corner squares</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Alignment patterns</strong>: help correct distortion</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Timing patterns</strong>: guide scanning across rows/columns</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Error correction</strong>: allows reading even if damaged</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list -->

<!-- wp:paragraph --></p>
<p id="viewer-ym5ej2628">The LVGL QR widget internally uses a compact QR generation algorithm, based on <strong>qrcodegen</strong>, optimized for embedded use. You won’t need to implement these patterns yourself, but understanding them helps debug issues (e.g., too much data, unreadable codes).</p>
<p><!-- /wp:paragraph -->

<!-- wp:heading --></p>
<h3 id="viewer-dn4u84903" class="wp-block-heading">Philosophy: More Than a Matrix</h3>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-mddb84968">What makes QR codes elegant is their <strong>balance between redundancy and compression</strong>. They:</p>
<p><!-- /wp:paragraph -->

<!-- wp:list --></p>
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Handle data loss gracefully with Reed-Solomon error correction</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Encode multiple formats (text, binary, etc.)</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Remain visually consistent while encoding vastly different content</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list -->

<!-- wp:paragraph --></p>
<p id="viewer-srst04982">In an embedded system, this philosophy matches our priorities: reliability, compactness, and clarity. With LVGL, you can embed this visual language into your UI effortlessly.</p>
<p><!-- /wp:paragraph -->

<!-- wp:heading --></p>
<h3 id="viewer-9d66j9531" class="wp-block-heading">LVGL QR Code Integration Limitations</h3>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-wqvwy9354">While the QR code widget in LVGL provides a convenient interface for rendering QR codes, it’s important to be aware of its design constraints and lack of configurability, especially if you need finer control for production-level applications.</p>
<p><!-- /wp:paragraph -->

<!-- wp:image --></p>
<figure class="wp-block-image"><img src="https://static.wixstatic.com/media/19c787_e39c29fe27a04c4cae006baf341b6446~mv2.png/v1/fill/w_704,h_268,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/19c787_e39c29fe27a04c4cae006baf341b6446~mv2.png" alt="" /></figure>
<p><!-- /wp:image -->

<!-- wp:heading --></p>
<h2 id="viewer-xgrz414059" class="wp-block-heading">&#x1f51a;Conclusion</h2>
<p><!-- /wp:heading -->

<!-- wp:paragraph --></p>
<p id="viewer-1st6j16193">LVGL’s QR code integration is simple, efficient, and well-suited for many embedded use cases, especially where memory and performance matter.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-c14q817836">It gets the job done when you need to display a basic QR code, and it integrates cleanly into the LVGL object model using lv_canvas. However, it stops short of offering full control. Features like error correction level, mask pattern selection, quiet zone size, and detailed error feedback are fixed or not exposed. For most developers, this may not be an issue, but for those needing fine-tuned QR generation (e.g., for branding, versioning, or resilience), the current implementation feels limiting.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-pf46d8135">That said… who knows? Maybe a patch is on the way to bring these missing features to LVGL. Stay tuned &#x1f609;</p>
<p><!-- /wp:paragraph --></p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Gabriel CATEL TORRES</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/embedded-user-interface/rendering-qr-codes-in-lvgl-from-pixels-to-philosophy/</guid>
                    </item>
				                    <item>
                        <title>Realtime embedded systems</title>
                        <link>https://edgemtech.ch/community/realtime-systems/realtime-embedded-systems/</link>
                        <pubDate>Sat, 10 Jan 2026 09:51:37 +0000</pubDate>
                        <description><![CDATA[Hard realtime systems is the third axis of competences we have at EDGEMTech.



It concerns all aspects (development, tuning and optimization, porting, debugging, etc.) related to hard r...]]></description>
                        <content:encoded><![CDATA[<p><!-- wp:paragraph --></p>
<p>Hard realtime systems is the third axis of competences we have at EDGEMTech.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-43mj61697">It concerns all aspects (development, tuning and optimization, porting, debugging, etc.) related to hard realtime systems (mainly x86 and ARM Linux-based systems).</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-pf46d8135">Do not hesitate to contact our expert <a href="mailto:daniel.rossier@edgemtech.ch" target="_blank" rel="noreferrer noopener"><u>Daniel Rossier</u></a> for any advice.</p>
<p><!-- /wp:paragraph --></p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Daniel Rossier</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/realtime-systems/realtime-embedded-systems/</guid>
                    </item>
				                    <item>
                        <title>x86 is far from being sidelined</title>
                        <link>https://edgemtech.ch/community/realtime-systems/x86-is-far-from-being-sidelined/</link>
                        <pubDate>Sat, 10 Jan 2026 09:51:00 +0000</pubDate>
                        <description><![CDATA[Have you ever thought that x86 would gradually leave the world of embedded systems?




The Sapphire Edge+ VPR-4616-MB is a Mini-ITX motherboard that includes the AMD Versal AI Edge VE2...]]></description>
                        <content:encoded><![CDATA[<p><!-- wp:paragraph --></p>
<p>Have you ever thought that x86 would gradually leave the world of embedded systems?</p>
<p><!-- /wp:paragraph -->

<!-- wp:quote --></p>
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>The Sapphire Edge+ VPR-4616-MB is a Mini-ITX motherboard that includes the AMD Versal AI Edge VE2302 device plus an AMD Ryzen Embedded R2314 processor, along with a flexible I/O interface to connect to various peripherals and sensors.</p>
<!-- /wp:paragraph --></blockquote>
<p><!-- /wp:quote -->

<!-- wp:image --></p>
<figure class="wp-block-image"><a class="m5Unu has-custom-focus zEYzC" href="https://www.amd.com/en/products/embedded/embedded-plus.html?utm_source=press+release&amp;utm_medium=referral&amp;utm_campaign=embedded-plus#product-brief"><img src="https://static.wixstatic.com/media/d1e2ca_f7be01a53ffc484698c180e77ecc266f~mv2.png/v1/fill/w_270,h_198,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/d1e2ca_f7be01a53ffc484698c180e77ecc266f~mv2.png" alt="" /></a></figure>
<p><!-- /wp:image -->

<!-- wp:paragraph --></p>
<p id="viewer-pf46d8135">Our Engineers are on hand to give you the necessary expertises in hard realtime systems based on Linux for your new development, if you envisage to start a new product or to port an existing realtime sy</p>
<p><!-- /wp:paragraph --></p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Daniel Rossier</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/realtime-systems/x86-is-far-from-being-sidelined/</guid>
                    </item>
				                    <item>
                        <title>EVL/Xenomai 4</title>
                        <link>https://edgemtech.ch/community/realtime-systems/evl-xenomai-4/</link>
                        <pubDate>Sat, 10 Jan 2026 09:50:10 +0000</pubDate>
                        <description><![CDATA[If your embedded system requires real-time constraints, don&#039;t worry! The Linux operating system remains a top choice. With significant advancements in the upstream RT-PREEMPT extension over ...]]></description>
                        <content:encoded><![CDATA[<p><!-- wp:paragraph --></p>
<p id="viewer-foo">If your embedded system requires real-time constraints, don't worry! The Linux operating system remains a top choice. With significant advancements in the upstream RT-PREEMPT extension over the past three years, you can now run applications on isolated CPU cores with minimal latency and jitter.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-n4tyt5681">However, some specific use cases—particularly those requiring hard real-time performance in user-space applications—can be tricky. Combining RT and non-RT tasks in the same environment may lead to interference, and implementing non-GPL closed-source code within the kernel only adds to the complexity.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-iatvv5683">For these challenges, the<u> </u><a href="https://evlproject.org/" target="_blank" rel="noreferrer noopener"><strong><u>EVL (Xenomai 4)</u></strong></a> extension is a powerful alternative to RT-PREEMPT. Here’s why</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-vy35i6091">:</p>
<p><!-- /wp:paragraph -->

<!-- wp:list --></p>
<ul class="wp-block-list"><!-- wp:list-item -->
<li><strong>Out-of-Band (OOB) Functions</strong>: Guarantee hard real-time conditions across execution paths, ensuring deterministic behavior for critical tasks.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Clean RT/Non-RT Separation</strong>: Isolates the real-time domain from standard Linux tasks, minimizing interference.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Scalable Architecture</strong>: Works seamlessly on popular ARM-based SoCs, such as Raspberry Pi, NXP, TI platforms, making it versatile for various embedded projects.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><strong>Hard Real-Time User-Space Applications</strong>: Ideal for scenarios where real-time functionality must remain closed-source without relying on kernel modifications.</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list -->

<!-- wp:paragraph --></p>
<p id="viewer-u9o0g5704">Whether you're tackling hard real-time constraints, maintaining user-space applications, or working with ARM-based systems, EVL offers an innovative and reliable solution.</p>
<p><!-- /wp:paragraph -->

<!-- wp:paragraph --></p>
<p id="viewer-omuum6633">It's definitely worth considering for your next project!</p>
<p><!-- /wp:paragraph --></p>]]></content:encoded>
						                            <category domain="https://edgemtech.ch/community/"></category>                        <dc:creator>Daniel Rossier</dc:creator>
                        <guid isPermaLink="true">https://edgemtech.ch/community/realtime-systems/evl-xenomai-4/</guid>
                    </item>
							        </channel>
        </rss>
		