<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Articles tagged zephyr at Royyan Dzakiy</title>
  <link rel="alternate" type="text/html"
        href="https://royyandzakiy.com/tags/zephyr/"/>
  <link rel="self" type="application/atom+xml"
        href="https://royyandzakiy.com/tags/zephyr/feed/"/>
  <updated>2026-10-16T09:06:07Z</updated>
  <id>urn:uuid:64cd9e68-0ee9-8fa2-bdfb-dec1abb45398</id>

  <author>
    <name>Royyan Dzakiy</name>
    <uri>https://royyandzakiy.com</uri>
  </author>

  <entry>
    <title>Zephyr App Event Manager (app_event_manager)</title>
    <link rel="alternate" type="text/html" href="https://royyandzakiy.com/blog/2026-04/app-event-manager-nrf-connect/"/>
    <id>urn:uuid:b19bb33c-a44d-5a0a-b6a5-5cd6c8cdf4e8</id>
    <updated>2026-04-06T00:00:00Z</updated>
    <category term="zephyr"/><category term="embedded"/>
    <content type="html">
      <![CDATA[<p>Another design of event-driven architecture is the <strong>AEM (app_event_manager)</strong> in Zephyr. This subsystem/framework enforces its users to structure their code in modules. Each module connected to the event-driven backend will need to explicitly subscribe/listen to another module to get notified of any events happening.</p>

<p>To me, this architecture style really helps when I need to isolate a particular module to debug or test easily. I could simply remove it from the CMakeLists.txt, and logically, the tight coupling design will not affect other modules.</p>

<p><a href="https://docs.nordicsemi.com/bundle/ncs-3.0.2/page/nrf/libraries/others/app_event_manager.html">https://docs.nordicsemi.com/bundle/ncs-3.0.2/page/nrf/libraries/others/app_event_manager.html</a></p>

<p>Here’s a small snippet of how it looks in practice:</p>

<pre class="highlight"><code><span class="c">/* --- Event Definition --- */</span>
APP_EVENT_TYPE_DEFINE(sensor_data_event,
		  <span class="k">NULL</span>,
		  <span class="k">NULL</span>,
		  APP_EVENT_FLAGS_CREATE(
			APP_EVENT_TYPE_FLAG_INIT_LOG_ENABLE
		  ));

<span class="c">/* --- Module A: Publisher --- */</span>
<span class="k">static</span> <span class="t">void</span> <span class="f">publish_sensor_data</span>(<span class="t">int32_t</span> value) {
	<span class="k">struct</span> <span class="t">sensor_data_event</span> *evt = new_sensor_data_event();
	evt-&gt;value = value;
	APP_EVENT_SUBMIT(evt);
}

<span class="c">/* --- Module B: Subscriber --- */</span>
<span class="k">static</span> <span class="t">bool</span> <span class="f">app_event_handler</span>(<span class="k">const</span> app_event_header *aeh) {
	<span class="k">if</span> (is_sensor_data_event(aeh)) {
		<span class="k">struct</span> <span class="t">sensor_data_event</span> *evt = cast_sensor_data_event(aeh);
		LOG_INF(<span class="s">"Received sensor data: %d"</span>, evt-&gt;value);
		<span class="k">return</span> <span class="k">true</span>;
	}
	<span class="k">return</span> <span class="k">false</span>;
}

APP_EVENT_LISTENER_DEFINE(sensor_event_listener, app_event_handler);
APP_EVENT_SUBSCRIBE(sensor_event_listener, <span class="t">sensor_data_event</span>);
</code></pre>

<p>With this approach, if I want to test Module B in isolation, I can simply remove Module A from the build, and the app still runs, it simply stops sending events. Really nice for unit testing and incremental development.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Zephyr Modern C++ - State Machine Size Comparison</title>
    <link rel="alternate" type="text/html" href="https://royyandzakiy.com/blog/2026-01/zephyr-cpp-vs-c-size/"/>
    <id>urn:uuid:0d1c8e4a-824d-5071-81bd-ab33d7526662</id>
    <updated>2026-01-12T00:00:00Z</updated>
    <category term="zephyr"/><category term="cpp"/><category term="statemachine"/>
    <content type="html">
      <![CDATA[<p>Can we use the latest C++ features on microcontrollers? <strong>Yes.</strong></p>

<p>I’ve been testing out to use it on Zephyr and ESP-IDF.</p>

<p>One particular feature I tried out in this example is the use of <code>std::variant</code> for different States, and ultimately using <code>std::visit</code> to iterate through them. Here I provide implementation of a general <code>get_state_info</code> to read what the current state is using the Overloaded Lambda idiom (to enforce availability of all StateVariants), it will then return a <code>std::string_view</code> of different messages based on the <code>current_state_</code>.</p>

<p>Let’s say, a more shiny StateMachine haha. A different approach than using bare enums and switch statements (not simply saying they are less).</p>

<p>Check it out!
<a href="https://github.com/royyandzakiy/zephyr-modern-cpp">https://github.com/royyandzakiy/zephyr-modern-cpp</a></p>

<!--more-->

<p>So far, there is a <strong>540 bytes difference</strong> when using <code>std::variant</code>/<code>std::visit</code>, compared to raw enum/switch.</p>

<p><strong>First build (std::variant/visit):</strong></p>
<ul>
  <li>FLASH: 73,112 bytes (6.97% of 1MB)</li>
  <li>RAM: 53,928 bytes (11.76% of 448KB)</li>
</ul>

<p><strong>Second build (enum/switch)</strong> (code depicted in image below):</p>
<ul>
  <li>FLASH: 72,572 bytes (6.92% of 1MB)</li>
  <li>RAM: 53,928 bytes (11.76% of 448KB)</li>
</ul>

<p>I also tried comparing when adding the C++ library to the compilation, and removing it. There is a <strong>4256 byte addition</strong>.</p>

<p><strong>Third build</strong> (converting all C++ to pure C &amp; but still compiling C++ library in kconfig):</p>
<ul>
  <li>FLASH: 71,588 bytes (6.83% of 1MB)</li>
  <li>RAM: 53,952 bytes (11.76% of 448KB)</li>
</ul>

<p><strong>Fourth build</strong> (converting all C++ to pure C &amp; removing C++ library in kconfig):</p>
<ul>
  <li>FLASH: 67,332 bytes (6.42% of 1MB)</li>
  <li>RAM: 53,840 bytes (11.74% of 448KB)</li>
</ul>

<p><strong>State machine using std::variant, std::visit</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_variant.png" alt="alt text" /></p>

<p><strong>State machine using enum &amp; switch</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_switch.png" alt="alt text" /></p>

<p><strong>Removing most all CPP code, change into C</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_c_cpp.png" alt="alt text" /></p>

<p><strong>Removing CPP lib in prj.conf</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_pure_c.png" alt="alt text" /></p>

<p><strong>Code using enum &amp; switch</strong></p>

<p><img src="/assets/images/zephyr-cpp-vs-c-size_recode_pure_c.png" alt="alt text" /></p>

<hr />

<p>The variant doesn’t add too much overhead. I was expecting a lot more bytes eaten up just by using Templates itself 😄</p>

<p>cc Srdjan Stokic</p>
]]>
    </content>
  </entry>

</feed>
