<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>freertos - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/freertos/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Thu, 19 Mar 2026 22:44:47 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>freertos - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Padrões de Projeto Aplicados a RTOS (FreeRTOS)</title>
		<link>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=padroes-de-projeto-aplicados-a-rtos-freertos-2</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 20 Mar 2026 08:29:27 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura de firmware]]></category>
		<category><![CDATA[comunicação entre tarefas FreeRTOS]]></category>
		<category><![CDATA[firmware robusto]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[inicialização em RTOS]]></category>
		<category><![CDATA[máquinas de estado em FreeRTOS]]></category>
		<category><![CDATA[mutex e gatekeeper FreeRTOS]]></category>
		<category><![CDATA[padrões de projeto embarcados]]></category>
		<category><![CDATA[RTOS em sistemas embarcados]]></category>
		<category><![CDATA[sistemas de tempo real]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1206</guid>

					<description><![CDATA[<p>Neste artigo apresentamos, de forma didática e aprofundada, os principais padrões de projeto aplicados a sistemas embarcados com FreeRTOS. O conteúdo aborda desde a estruturação de tarefas, comunicação e sincronização, proteção de recursos e controle de estados, até arquitetura em camadas, inicialização segura e monitoramento de saúde do sistema. Com exemplos práticos em C e foco em aplicações reais, o artigo mostra como usar padrões para construir firmware robusto, previsível e escalável, adequado a ambientes industriais, IoT e sistemas críticos de tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/">Padrões de Projeto Aplicados a RTOS (FreeRTOS)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introdução geral</h2>



<p class="wp-block-paragraph">Em sistemas embarcados com RTOS, especialmente em aplicações industriais, automotivas e IoT crítico, o maior desafio não é apenas “fazer funcionar”, mas <strong>manter previsibilidade temporal, escalabilidade e manutenibilidade</strong>. É nesse ponto que os <strong>padrões de projeto aplicados a RTOS</strong> se tornam fundamentais.</p>



<p class="wp-block-paragraph">Diferente de aplicações desktop, padrões em RTOS precisam respeitar <strong>restrições de tempo real</strong>, <strong>uso determinístico de memória</strong>, <strong>prioridades</strong>, <strong>latência de interrupções</strong> e <strong>sincronização segura entre contexto de ISR e tarefas</strong>. Muitos padrões clássicos de software são adaptados ou reinterpretados nesse contexto.</p>



<p class="wp-block-paragraph">Neste artigo, começaremos pelos <strong>padrões estruturais básicos de tarefas</strong>, que formam a fundação de praticamente qualquer sistema com FreeRTOS.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1 – Padrões Fundamentais de Estruturação de Tarefas</h2>



<h3 class="wp-block-heading">1.1 Superloop + Tasks (Incremental RTOS Adoption)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Projetos legados em superloop (<code>while(1)</code>) tornam-se difíceis de manter à medida que crescem. Migrar tudo de uma vez para RTOS é arriscado.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Manter o superloop como uma <strong>tarefa principal</strong>, introduzindo gradualmente novas tarefas RTOS.</p>



<p class="wp-block-paragraph"><strong>Quando usar:</strong></p>



<ul class="wp-block-list">
<li>Migração de firmware bare-metal para FreeRTOS</li>



<li>Sistemas simples que estão crescendo</li>



<li>Prototipação controlada</li>
</ul>



<p class="wp-block-paragraph"><strong>Estrutura típica:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void LegacySuperloopTask(void *pvParameters)
{
    for (;;)
    {
        ReadSensors();
        ProcessData();
        UpdateOutputs();

        vTaskDelay(pdMS_TO_TICKS(10));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">LegacySuperloopTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ReadSensors</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ProcessData</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">UpdateOutputs</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xTaskCreate(
    LegacySuperloopTask,
    "Legacy",
    1024,
    NULL,
    tskIDLE_PRIORITY + 1,
    NULL
);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">LegacySuperloopTask</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Legacy</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">1024</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">NULL</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Baixo risco na migração</li>



<li>Preserva código validado</li>



<li>Facilita testes incrementais</li>
</ul>



<p class="wp-block-paragraph"><strong>Risco comum:</strong><br>Transformar essa tarefa em um “monstro” que ignora o espírito do RTOS. Este padrão <strong>deve ser transitório</strong>, não permanente.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Tarefas que fazem “de tudo” dificultam análise temporal, debugging e escalonamento.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada tarefa possui <strong>uma única responsabilidade funcional bem definida</strong>.</p>



<p class="wp-block-paragraph"><strong>Exemplo típico em FreeRTOS:</strong></p>



<ul class="wp-block-list">
<li>Task de aquisição</li>



<li>Task de processamento</li>



<li>Task de comunicação</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void SensorTask(void *pvParameters)
{
    for (;;)
    {
        ReadADC();
        xTaskNotify(ProcessTaskHandle, 0, eNoAction);
        vTaskDelay(pdMS_TO_TICKS(5));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SensorTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ReadADC</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ProcessTaskHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void ProcessTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        FilterData();
        ComputeResults();
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ProcessTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ulTaskNotifyTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pdTRUE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">FilterData</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ComputeResults</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Facilita análise de prioridades</li>



<li>Reduz acoplamento</li>



<li>Favorece paralelismo real</li>
</ul>



<p class="wp-block-paragraph"><strong>Boas práticas:</strong></p>



<ul class="wp-block-list">
<li>Nomear tarefas claramente</li>



<li>Documentar WCET (Worst Case Execution Time)</li>



<li>Evitar bloqueios longos</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.3 Cyclic Executive com RTOS</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Algumas aplicações precisam de <strong>periodicidade rígida</strong>, mesmo usando RTOS.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Uma tarefa de alta prioridade atua como <strong>orquestrador temporal</strong>, liberando outras tarefas de forma cíclica.</p>



<p class="wp-block-paragraph"><strong>Estrutura conceitual:</strong></p>



<ul class="wp-block-list">
<li>Task cíclica principal</li>



<li>Subtarefas acionadas por notificações</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void CyclicTask(void *pvParameters)
{
    TickType_t xLastWakeTime = xTaskGetTickCount();

    for (;;)
    {
        xTaskNotify(TaskAHandle, 0, eNoAction);
        xTaskNotify(TaskBHandle, 0, eNoAction);

        vTaskDelayUntil(&amp;xLastWakeTime, pdMS_TO_TICKS(10));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">CyclicTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">TickType_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xLastWakeTime</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xTaskGetTickCount</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TaskAHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TaskBHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelayUntil</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">xLastWakeTime</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Controle temporal explícito</li>



<li>Previsibilidade elevada</li>



<li>Útil em controle e automação</li>
</ul>



<p class="wp-block-paragraph"><strong>Limitação:</strong><br>Menos flexível que arquiteturas puramente orientadas a eventos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.4 Idle Task como Padrão Arquitetural</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Desperdício de CPU e energia quando o sistema está ocioso.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Usar a <strong>Idle Task</strong> como ponto central para:</p>



<ul class="wp-block-list">
<li>Economia de energia</li>



<li>Limpeza de recursos</li>



<li>Instrumentação</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void vApplicationIdleHook(void)
{
    EnterLowPowerMode();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vApplicationIdleHook</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">EnterLowPowerMode</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Uso típico:</strong></p>



<ul class="wp-block-list">
<li><code>__WFI()</code> em Cortex-M</li>



<li>Estatísticas de CPU</li>



<li>Monitoramento de heap</li>
</ul>



<p class="wp-block-paragraph"><strong>Importante:</strong><br>Nunca bloquear, nunca usar delays e nunca acessar recursos não protegidos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2 – Padrões de Comunicação e Sincronização em RTOS</h2>



<p class="wp-block-paragraph">Em FreeRTOS, <strong>concorrência mal projetada é a principal fonte de bugs</strong>: deadlocks, starvation, jitter temporal e corrupção de dados. Os padrões desta seção existem para <strong>substituir variáveis globais, flags soltas e <code>volatile</code> mal utilizados</strong> por mecanismos determinísticos e auditáveis.</p>



<p class="wp-block-paragraph">Aqui falamos de <strong>comunicação</strong>, não apenas de sincronização.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.1 Event Queue (Fila de Eventos)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Múltiplos produtores gerando eventos assíncronos para um único consumidor.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Eventos são encapsulados em estruturas e enviados por uma fila RTOS. O consumidor processa eventos <strong>em ordem temporal</strong>.</p>



<p class="wp-block-paragraph"><strong>Quando usar:</strong></p>



<ul class="wp-block-list">
<li>Interface homem-máquina</li>



<li>Eventos de sensores</li>



<li>Drivers desacoplados da lógica de aplicação</li>
</ul>



<p class="wp-block-paragraph"><strong>Estrutura típica do evento:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef enum {
    EVT_BUTTON,
    EVT_SENSOR,
    EVT_TIMEOUT
} EventType;

typedef struct {
    EventType type;
    uint32_t  data;
} AppEvent;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">EVT_BUTTON</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">EVT_SENSOR</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">EVT_TIMEOUT</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EventType</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">EventType</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">type</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">data</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AppEvent</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Fila global (criada na inicialização):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>QueueHandle_t EventQueue;

EventQueue = xQueueCreate(10, sizeof(AppEvent));
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EventQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">EventQueue</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xQueueCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AppEvent</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Produtor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void ButtonISR(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    AppEvent evt = {
        .type = EVT_BUTTON,
        .data = 1
    };

    xQueueSendFromISR(EventQueue, &amp;evt, &amp;xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ButtonISR</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">BaseType_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdFALSE</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">AppEvent</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">evt</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        .</span><span style="color: #D8DEE9">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_BUTTON</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        .</span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xQueueSendFromISR</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">EventQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">portYIELD_FROM_ISR</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Consumidor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void EventTask(void *pvParameters)
{
    AppEvent evt;

    for (;;)
    {
        if (xQueueReceive(EventQueue, &amp;evt, portMAX_DELAY))
        {
            switch (evt.type)
            {
                case EVT_BUTTON:
                    HandleButton(evt.data);
                    break;

                case EVT_SENSOR:
                    HandleSensor(evt.data);
                    break;

                default:
                    break;
            }
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EventTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">AppEvent</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">evt</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">EventQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">switch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">type</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_BUTTON</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">HandleButton</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_SENSOR</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">HandleSensor</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">default</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Desacoplamento total</li>



<li>Ordem garantida</li>



<li>Fácil instrumentação</li>
</ul>



<p class="wp-block-paragraph"><strong>Erro comum:</strong><br>Usar fila para <strong>stream contínuo de dados</strong> (para isso existem buffers).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.2 Mailbox (Fila de Mensagem Única)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Apenas <strong>o último valor importa</strong>, não o histórico.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Uma fila de tamanho 1 funciona como <strong>mailbox sobrescrevível</strong>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>QueueHandle_t Mailbox;

Mailbox = xQueueCreate(1, sizeof(uint32_t));
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Mailbox</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">Mailbox</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xQueueCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Produtor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>uint32_t temperature = ReadTemperature();
xQueueOverwrite(Mailbox, &amp;temperature);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temperature</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ReadTemperature</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">xQueueOverwrite</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">Mailbox</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">temperature</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Consumidor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>uint32_t temp;

if (xQueuePeek(Mailbox, &amp;temp, 0))
{
    UseTemperature(temp);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temp</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueuePeek</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">Mailbox</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">temp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">UseTemperature</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Quando usar:</strong></p>



<ul class="wp-block-list">
<li>Telemetria</li>



<li>Estados globais observáveis</li>



<li>Última leitura válida</li>
</ul>



<p class="wp-block-paragraph"><strong>Vantagem-chave:</strong><br>Evita backlog artificial.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.3 Publish–Subscribe (Pub-Sub) com FreeRTOS</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Múltiplos consumidores interessados no mesmo evento.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Uma tarefa “dispatcher” recebe eventos e os redistribui para múltiplas filas.</p>



<p class="wp-block-paragraph"><strong>Arquitetura:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ISR / Producers
      ↓
  Event Queue
      ↓
  Dispatcher Task
     ↓          ↓           ↓
 Task A Task B Task C
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">ISR</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Producers</span></span>
<span class="line"><span style="color: #D8DEE9FF">      ↓</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">Event</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Queue</span></span>
<span class="line"><span style="color: #D8DEE9FF">      ↓</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">Dispatcher</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Task</span></span>
<span class="line"><span style="color: #D8DEE9FF">     ↓          ↓           ↓</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Task</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">A</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Task</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">B</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Task</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Dispatcher:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void DispatcherTask(void *pvParameters)
{
    AppEvent evt;

    for (;;)
    {
        if (xQueueReceive(EventQueue, &amp;evt, portMAX_DELAY))
        {
            xQueueSend(QueueA, &amp;evt, 0);
            xQueueSend(QueueB, &amp;evt, 0);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">DispatcherTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">AppEvent</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">evt</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">EventQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">QueueA</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">QueueB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">evt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Extensível</li>



<li>Isola produtores de consumidores</li>



<li>Facilita testes</li>
</ul>



<p class="wp-block-paragraph"><strong>Custo:</strong><br>Mais RAM e latência — aceitável em troca de clareza.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.4 Task Notification como Padrão de Sinalização Rápida</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Overhead de filas quando apenas <strong>sinalização simples</strong> é necessária.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Usar <strong>Task Notifications</strong> como semáforos ultraleves.</p>



<p class="wp-block-paragraph"><strong>Produtor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xTaskNotify(TaskHandle, 0x01, eSetBits);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TaskHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x01</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eSetBits</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Consumidor:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>uint32_t flags;

xTaskNotifyWait(0, 0xFFFFFFFF, &amp;flags, portMAX_DELAY);

if (flags &amp; 0x01)
{
    ProcessEvent();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">flags</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">xTaskNotifyWait</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0xFFFFFFFF</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">flags</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">flags</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x01</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ProcessEvent</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Zero alocação dinâmica</li>



<li>Extremamente rápido</li>



<li>Ideal para ISR → Task</li>
</ul>



<p class="wp-block-paragraph"><strong>Limitação:</strong><br>Apenas 32 bits por tarefa → não serve para dados complexos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.5 Stream Buffer e Message Buffer</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Troca eficiente de <strong>fluxos contínuos</strong> de dados.</p>



<h4 class="wp-block-heading">Stream Buffer</h4>



<ul class="wp-block-list">
<li>Dados binários contínuos</li>



<li>Sem fronteira de mensagem</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>StreamBufferHandle_t sb;
sb = xStreamBufferCreate(128, 1);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">StreamBufferHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sb</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">sb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xStreamBufferCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading">Message Buffer</h4>



<ul class="wp-block-list">
<li>Mensagens delimitadas</li>



<li>Ideal para pacotes</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>MessageBufferHandle_t mb;
mb = xMessageBufferCreate(128);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">MessageBufferHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mb</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">mb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xMessageBufferCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">128</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Uso típico:</strong></p>



<ul class="wp-block-list">
<li>UART</li>



<li>SPI</li>



<li>Áudio</li>



<li>Protocolos binários</li>
</ul>



<p class="wp-block-paragraph"><strong>Boa prática:</strong><br>Preferir buffers a filas para dados “em volume”.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3 – Padrões de Exclusão Mútua, Proteção de Recursos e Prevenção de Deadlock</h2>



<p class="wp-block-paragraph">Em FreeRTOS, <strong>concorrência não controlada não falha sempre — falha quando você menos espera</strong>. Esta seção trata de padrões que <strong>evitam corrupção de dados, inversão de prioridade e deadlocks</strong>, sem sacrificar o determinismo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.1 Mutex com Priority Inheritance</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Duas ou mais tarefas acessam o mesmo recurso (UART, I²C, SPI, memória compartilhada).</p>



<p class="wp-block-paragraph"><strong>Risco clássico:</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <em>Priority Inversion</em> — tarefa de baixa prioridade bloqueia uma de alta.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Usar <strong>Mutex (não semáforo)</strong> para herança de prioridade automática.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>SemaphoreHandle_t uartMutex;

uartMutex = xSemaphoreCreateMutex();
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartMutex</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">uartMutex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xSemaphoreCreateMutex</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Uso correto:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void UartTask(void *pvParameters)
{
    for (;;)
    {
        if (xSemaphoreTake(uartMutex, portMAX_DELAY))
        {
            UART_Write("Hello RTOS\n");
            xSemaphoreGive(uartMutex);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">UartTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uartMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">UART_Write</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Hello RTOS</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uartMutex</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Por que não semáforo binário?</strong></p>



<ul class="wp-block-list">
<li>Semáforos <strong>não fazem herança de prioridade</strong></li>



<li>Mutexes são projetados para exclusão mútua real</li>
</ul>



<p class="wp-block-paragraph"><strong>Regra de ouro:</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f512.png" alt="🔒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <em>Mutex protege recurso, não evento.</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.2 Gatekeeper Task (Padrão Fundamental em FreeRTOS)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Múltiplas tarefas acessando um <strong>único periférico</strong> (UART, Flash, Display).</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Apenas <strong>uma tarefa é dona do recurso</strong>. As demais <strong>pedem serviço</strong> via fila.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Este é um dos padrões mais importantes para firmware de produção.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Estrutura:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Tasks ──► Request Queue ──► Gatekeeper Task ──► Hardware
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Tasks</span><span style="color: #D8DEE9FF"> ──► </span><span style="color: #D8DEE9">Request</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Queue</span><span style="color: #D8DEE9FF"> ──► </span><span style="color: #D8DEE9">Gatekeeper</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Task</span><span style="color: #D8DEE9FF"> ──► </span><span style="color: #D8DEE9">Hardware</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Mensagem de requisição:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
    char message&#91;64&#93;;
} UartRequest;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">message</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">64</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">UartRequest</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Gatekeeper:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void UartGatekeeperTask(void *pvParameters)
{
    UartRequest req;

    for (;;)
    {
        if (xQueueReceive(UartQueue, &amp;req, portMAX_DELAY))
        {
            UART_Write(req.message);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">UartGatekeeperTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">UartRequest</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">req</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UartQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">req</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">UART_Write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">req</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">message</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Cliente:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>UartRequest req = { .message = "Log message\n" };
xQueueSend(UartQueue, &amp;req, portMAX_DELAY);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">UartRequest</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">req</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> .</span><span style="color: #D8DEE9">message</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Log message</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UartQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">req</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Elimina mutexes</li>



<li>Elimina deadlocks</li>



<li>Simplifica drivers</li>
</ul>



<p class="wp-block-paragraph"><strong>Trade-off:</strong><br>Leve aumento de latência → ganho enorme em robustez.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.3 Critical Section (Uso cirúrgico)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Trechos <strong>extremamente curtos</strong> que não podem ser interrompidos.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>taskENTER_CRITICAL();
sharedCounter++;
taskEXIT_CRITICAL();
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">taskENTER_CRITICAL</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">sharedCounter</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #88C0D0">taskEXIT_CRITICAL</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>O que acontece:</strong></p>



<ul class="wp-block-list">
<li>Desabilita interrupções (localmente)</li>



<li>Bloqueia escalonamento</li>
</ul>



<p class="wp-block-paragraph"><strong>Quando usar:</strong></p>



<ul class="wp-block-list">
<li>Incrementos atômicos</li>



<li>Flags simples</li>



<li>Estruturas lock-free auxiliares</li>
</ul>



<p class="wp-block-paragraph"><strong>Quando NÃO usar:</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Código longo<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Acesso a drivers<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comunicação entre tarefas</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Se você precisa de <code>printf()</code> dentro de critical section, algo está errado.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.4 Read–Modify–Write protegido (Anti-pattern clássico)</h3>



<p class="wp-block-paragraph"><strong>Problema comum (ERRADO):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>if (flag == 0)
{
    flag = 1;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">flag</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">flag</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Correção com mutex:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xSemaphoreTake(flagMutex, portMAX_DELAY);
if (flag == 0)
{
    flag = 1;
}
xSemaphoreGive(flagMutex);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">flagMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">flag</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">flag</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">flagMutex</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Ou melhor ainda:</strong><br>Substituir <code>flag</code> por <strong>task notification</strong> ou <strong>event group</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.5 Event Groups como Padrão de Coordenação</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Sincronizar múltiplas tarefas com <strong>condições compostas</strong>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>EventGroupHandle_t systemEvents;

#define EVT_NET_READY   (1 &lt;&lt; 0)
#define EVT_SENSOR_OK   (1 &lt;&lt; 1)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">EventGroupHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">systemEvents</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EVT_NET_READY</span><span style="color: #D8DEE9FF">   (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EVT_SENSOR_OK</span><span style="color: #D8DEE9FF">   (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sinalização:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xEventGroupSetBits(systemEvents, EVT_NET_READY);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xEventGroupSetBits</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">systemEvents</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_NET_READY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Aguardar múltiplas condições:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xEventGroupWaitBits(
    systemEvents,
    EVT_NET_READY | EVT_SENSOR_OK,
    pdFALSE,
    pdTRUE,
    portMAX_DELAY
);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xEventGroupWaitBits</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">systemEvents</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">EVT_NET_READY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_SENSOR_OK</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pdFALSE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pdTRUE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">portMAX_DELAY</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Uso típico:</strong></p>



<ul class="wp-block-list">
<li>Startup sequencial</li>



<li>Estados globais do sistema</li>



<li>Dependências entre subsistemas</li>
</ul>



<p class="wp-block-paragraph"><strong>Vantagem:</strong><br>Muito mais expressivo que flags globais.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.6 Deadlock Avoidance (Padrões de Prevenção)</h3>



<p class="wp-block-paragraph"><strong>Causa clássica de deadlock:</strong></p>



<ul class="wp-block-list">
<li>Ordem inconsistente de aquisição de mutexes</li>
</ul>



<p class="wp-block-paragraph"><strong>Padrão de prevenção:</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d0.png" alt="📐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <em>Sempre adquirir recursos na mesma ordem</em></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xSemaphoreTake(mutexA, portMAX_DELAY);
xSemaphoreTake(mutexB, portMAX_DELAY);

/* uso */

xSemaphoreGive(mutexB);
xSemaphoreGive(mutexA);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">mutexA</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">mutexB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* uso */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">mutexB</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">mutexA</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Alternativa mais segura:</strong><br>Eliminar múltiplos mutexes → usar <strong>Gatekeeper</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4 – Padrões de Controle de Fluxo, Estados e Recuperação em RTOS</h2>



<p class="wp-block-paragraph">Em sistemas com FreeRTOS, <strong>fluxo implícito é inimigo do determinismo</strong>. <code>if</code> encadeado, flags globais e dependências ocultas tornam o comportamento do sistema impossível de prever sob carga, falhas ou eventos raros.</p>



<p class="wp-block-paragraph">Os padrões desta seção tornam o <strong>comportamento do sistema explícito, rastreável e recuperável</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.1 State Machine (Máquina de Estados Finita – FSM)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Fluxo de controle espalhado por múltiplas tarefas e condicionais.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Representar o comportamento como <strong>estados explícitos</strong> e <strong>transições bem definidas</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Estrutura básica</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef enum {
    STATE_INIT,
    STATE_IDLE,
    STATE_ACTIVE,
    STATE_ERROR
} SystemState;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">STATE_INIT</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">STATE_IDLE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">STATE_ACTIVE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">STATE_ERROR</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SystemState</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static SystemState currentState = STATE_INIT;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SystemState</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_INIT</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Execução da máquina de estados (task dedicada)</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void StateMachineTask(void *pvParameters)
{
    for (;;)
    {
        switch (currentState)
        {
            case STATE_INIT:
                InitHardware();
                currentState = STATE_IDLE;
                break;

            case STATE_IDLE:
                if (StartCondition())
                    currentState = STATE_ACTIVE;
                break;

            case STATE_ACTIVE:
                RunControlLoop();
                if (FaultDetected())
                    currentState = STATE_ERROR;
                break;

            case STATE_ERROR:
                HandleFault();
                currentState = STATE_IDLE;
                break;
        }

        vTaskDelay(pdMS_TO_TICKS(10));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">StateMachineTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">switch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_INIT</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">InitHardware</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_IDLE</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_IDLE</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">StartCondition</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_ACTIVE</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_ACTIVE</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">RunControlLoop</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">FaultDetected</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_ERROR</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_ERROR</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">HandleFault</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_IDLE</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Fluxo claro</li>



<li>Fácil depuração</li>



<li>Excelente para controle e sequenciamento</li>
</ul>



<p class="wp-block-paragraph"><strong>Limitação:</strong><br>Cresce mal quando há muitos estados e eventos → entra a HSM.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.2 Hierarchical State Machine (HSM)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Explosão combinatória de estados.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Estados possuem <strong>comportamento comum herdado</strong> de estados “pais”.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo conceitual</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>SYSTEM
 ├── OPERATIONAL
 │    ├── IDLE
 │    └── ACTIVE
 └── FAULT
      ├── WARNING
      └── CRITICAL
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">SYSTEM</span></span>
<span class="line"><span style="color: #D8DEE9FF"> ├── </span><span style="color: #D8DEE9">OPERATIONAL</span></span>
<span class="line"><span style="color: #D8DEE9FF"> │    ├── </span><span style="color: #D8DEE9">IDLE</span></span>
<span class="line"><span style="color: #D8DEE9FF"> │    └── </span><span style="color: #D8DEE9">ACTIVE</span></span>
<span class="line"><span style="color: #D8DEE9FF"> └── </span><span style="color: #D8DEE9">FAULT</span></span>
<span class="line"><span style="color: #D8DEE9FF">      ├── </span><span style="color: #D8DEE9">WARNING</span></span>
<span class="line"><span style="color: #D8DEE9FF">      └── </span><span style="color: #D8DEE9">CRITICAL</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Implementação simplificada em C</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef enum {
    SUPER_OPERATIONAL,
    SUPER_FAULT
} SuperState;

typedef enum {
    SUB_IDLE,
    SUB_ACTIVE,
    SUB_WARNING,
    SUB_CRITICAL
} SubState;

static SuperState superState;
static SubState   subState;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUPER_OPERATIONAL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUPER_FAULT</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SuperState</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUB_IDLE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUB_ACTIVE</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUB_WARNING</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SUB_CRITICAL</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SubState</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SuperState</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">superState</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SubState</span><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">subState</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void StateMachineStep(void)
{
    switch (superState)
    {
        case SUPER_OPERATIONAL:
            if (FaultDetected())
            {
                superState = SUPER_FAULT;
                subState = SUB_WARNING;
                break;
            }

            if (subState == SUB_IDLE &amp;&amp; StartCondition())
                subState = SUB_ACTIVE;

            break;

        case SUPER_FAULT:
            HandleFaultCommon();

            if (subState == SUB_WARNING &amp;&amp; EscalateFault())
                subState = SUB_CRITICAL;

            if (FaultCleared())
            {
                superState = SUPER_OPERATIONAL;
                subState = SUB_IDLE;
            }
            break;
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">StateMachineStep</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">switch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">superState</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUPER_OPERATIONAL</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">FaultDetected</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">superState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUPER_FAULT</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_WARNING</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_IDLE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">StartCondition</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_ACTIVE</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUPER_FAULT</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">HandleFaultCommon</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_WARNING</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EscalateFault</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_CRITICAL</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">FaultCleared</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">superState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUPER_OPERATIONAL</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">subState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SUB_IDLE</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Redução de duplicação</li>



<li>Escala bem</li>



<li>Muito usada em automotivo e aeroespacial</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.3 Mode Manager (Gerenciador de Modos)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Múltiplas tarefas precisam reagir a <strong>mudanças globais de modo</strong>.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Uma tarefa central gerencia o <strong>modo do sistema</strong>, e os demais módulos <strong>se adaptam</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Modos típicos</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef enum {
    MODE_STARTUP,
    MODE_NORMAL,
    MODE_LOW_POWER,
    MODE_MAINTENANCE
} SystemMode;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MODE_STARTUP</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MODE_NORMAL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MODE_LOW_POWER</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MODE_MAINTENANCE</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SystemMode</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Mode Manager</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static SystemMode currentMode;

void ModeManagerTask(void *pvParameters)
{
    for (;;)
    {
        if (LowPowerRequested())
            currentMode = MODE_LOW_POWER;

        if (MaintenanceRequested())
            currentMode = MODE_MAINTENANCE;

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SystemMode</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">currentMode</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ModeManagerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">LowPowerRequested</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">currentMode</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MODE_LOW_POWER</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">MaintenanceRequested</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">currentMode</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MODE_MAINTENANCE</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Uso pelas tarefas</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void SensorTask(void *pvParameters)
{
    for (;;)
    {
        if (currentMode == MODE_NORMAL)
            ReadSensors();

        vTaskDelay(pdMS_TO_TICKS(50));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SensorTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">currentMode</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MODE_NORMAL</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">ReadSensors</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">50</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Boa prática:</strong><br>Substituir variável global por:</p>



<ul class="wp-block-list">
<li>Event Groups</li>



<li>Message Queue</li>



<li>Broadcast via Pub-Sub</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.4 Recovery Pattern (Padrão de Recuperação)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Falhas transitórias travam o sistema.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Falhas são tratadas como <strong>estados</strong>, não exceções implícitas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo de recuperação controlada</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>case STATE_ERROR:
    LogFault();
    ResetSubsystem();
    if (RetryAllowed())
        currentState = STATE_INIT;
    else
        EnterSafeState();
    break;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> STATE_ERROR</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">LogFault</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ResetSubsystem</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">RetryAllowed</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">currentState</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATE_INIT</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">EnterSafeState</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Evita reboot desnecessário</li>



<li>Permite retry controlado</li>



<li>Essencial para sistemas remotos</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.5 Watchdog como Padrão Arquitetural</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Deadlocks silenciosos e travamentos não detectados.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada tarefa <strong>sinaliza vida</strong> periodicamente para um supervisor.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void SupervisorTask(void *pvParameters)
{
    for (;;)
    {
        if (!AllTasksAlive())
            SystemReset();

        FeedWatchdog();
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SupervisorTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">AllTasksAlive</span><span style="color: #D8DEE9FF">())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">SystemReset</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">FeedWatchdog</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Importante:</strong><br>O watchdog <strong>não substitui</strong> arquitetura correta — ele a complementa.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Excelente. Agora avançamos para a <strong>arquitetura interna do firmware</strong>, onde decisões erradas costumam gerar <strong>acoplamento irreversível</strong>, e decisões corretas permitem <strong>portabilidade, testes e evolução por anos</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5 – Padrões de Arquitetura em Camadas, Drivers e Serviços em RTOS</h2>



<p class="wp-block-paragraph">Em sistemas com FreeRTOS, <strong>misturar driver, lógica de negócio e política de tempo real na mesma tarefa é um erro estrutural</strong>. Os padrões desta seção tratam de <strong>separação de responsabilidades</strong>, <strong>isolamento de hardware</strong> e <strong>execução previsível</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.1 Layered Architecture (Arquitetura em Camadas)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Firmware “espaguete”, onde qualquer módulo acessa diretamente registradores, RTOS e aplicação.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Organizar o sistema em <strong>camadas bem definidas</strong>, com dependências unidirecionais.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Camadas típicas em FreeRTOS</h4>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>Application / State Machines</td></tr><tr><td>Services (Comms, Storage)</td></tr><tr><td>Drivers / HAL</td></tr><tr><td>RTOS (FreeRTOS Kernel)</td></tr><tr><td>Hardware</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo de separação correta</h4>



<p class="wp-block-paragraph"><strong>Driver (HAL):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void UartHw_SendByte(uint8_t b);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void UartHw_SendByte(uint8_t b);</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Serviço:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void UartService_Send(const uint8_t *data, size_t len);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void UartService_Send(const uint8_t *data, size_t len);</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Aplicação:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>UartService_Send((uint8_t*)"OK\n", 3);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">UartService_Send((uint8_t*)&quot;OK\n&quot;, 3);</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Portabilidade de MCU</li>



<li>Testes unitários viáveis</li>



<li>Evolução controlada</li>
</ul>



<p class="wp-block-paragraph"><strong>Regra prática:</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b06.png" alt="⬆" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Camadas superiores <strong>não conhecem</strong> detalhes das inferiores.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.2 Hardware Abstraction Layer (HAL) como Padrão</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Dependência direta de registradores ou SDK do fabricante.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Isolar acesso ao hardware atrás de uma <strong>API mínima e estável</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
    void (*init)(void);
    void (*write)(const uint8_t *buf, size_t len);
} UartDriver;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">typedef struct {</span></span>
<span class="line"><span style="color: #D8DEE9FF">    void (*init)(void);</span></span>
<span class="line"><span style="color: #D8DEE9FF">    void (*write)(const uint8_t *buf, size_t len);</span></span>
<span class="line"><span style="color: #D8DEE9FF">} UartDriver;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static UartDriver uart0 = {
    .init  = STM32_UartInit,
    .write = STM32_UartWrite
};
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">static UartDriver uart0 = {</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .init  = STM32_UartInit,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .write = STM32_UartWrite</span></span>
<span class="line"><span style="color: #D8DEE9FF">};</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Benefício crítico:</strong><br>Permite trocar STM32 → NXP → RP2040 <strong>sem reescrever aplicação</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.3 Service Layer (Camada de Serviços)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Drivers não devem conter lógica de negócio nem política de concorrência.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Serviços encapsulam:</p>



<ul class="wp-block-list">
<li>Sincronização</li>



<li>Filas</li>



<li>Retries</li>



<li>Timeout</li>



<li>Políticas de acesso</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo: Serviço de UART com Gatekeeper</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void UartService_Send(const uint8_t *data, size_t len)
{
    UartRequest req = {
        .data = data,
        .len  = len
    };

    xQueueSend(UartQueue, &amp;req, portMAX_DELAY);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void UartService_Send(const uint8_t *data, size_t len)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    UartRequest req = {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        .data = data,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        .len  = len</span></span>
<span class="line"><span style="color: #D8DEE9FF">    };</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    xQueueSend(UartQueue, &amp;req, portMAX_DELAY);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Aplicação fica limpa</li>



<li>Política centralizada</li>



<li>Drivers permanecem simples</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.4 Active Object Pattern</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Misturar lógica de controle com concorrência explícita.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada objeto ativo possui:</p>



<ul class="wp-block-list">
<li>Estado interno</li>



<li>Fila própria</li>



<li>Tarefa dedicada</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Estrutura conceitual</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Active Object
 ├── Queue
 ├── Task
 └── State Machine
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Active Object</span></span>
<span class="line"><span style="color: #D8DEE9FF"> ├── Queue</span></span>
<span class="line"><span style="color: #D8DEE9FF"> ├── Task</span></span>
<span class="line"><span style="color: #D8DEE9FF"> └── State Machine</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo simplificado</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
    QueueHandle_t queue;
} MotorController;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">typedef struct {</span></span>
<span class="line"><span style="color: #D8DEE9FF">    QueueHandle_t queue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">} MotorController;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void MotorTask(void *pvParameters)
{
    MotorCommand cmd;

    for (;;)
    {
        xQueueReceive(motor.queue, &amp;cmd, portMAX_DELAY);
        ExecuteMotorCommand(&amp;cmd);
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void MotorTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    MotorCommand cmd;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    for (;;)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        xQueueReceive(motor.queue, &amp;cmd, portMAX_DELAY);</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ExecuteMotorCommand(&amp;cmd);</span></span>
<span class="line"><span style="color: #D8DEE9FF">    }</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Forte encapsulamento</li>



<li>Ideal para controle, comunicação e I/O</li>



<li>Elimina mutexes internos</li>
</ul>



<p class="wp-block-paragraph"><strong>Custo:</strong><br>Uso maior de RAM (1 task + 1 fila por objeto)</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.5 Deferred Interrupt Processing</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>ISR longa causa jitter e perda de deadlines.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>ISR apenas <strong>sinaliza</strong> → processamento pesado ocorre em task.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void ADC_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xTaskNotifyFromISR(AdcTaskHandle, 0, eNoAction, &amp;xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void ADC_IRQHandler(void)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    BaseType_t xHigherPriorityTaskWoken = pdFALSE;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xTaskNotifyFromISR(AdcTaskHandle, 0, eNoAction, &amp;xHigherPriorityTaskWoken);</span></span>
<span class="line"><span style="color: #D8DEE9FF">    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void AdcTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        ProcessAdcData();
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void AdcTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    for (;;)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ProcessAdcData();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    }</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>ISR mínima</li>



<li>Melhor escalonamento</li>



<li>Sistema mais previsível</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"> 6 – Padrões de Inicialização, Startup Sequencial e Monitoramento de Saúde</h2>



<p class="wp-block-paragraph">Em sistemas com FreeRTOS, <strong>o boot é o momento mais frágil do sistema</strong>. Muitos firmwares falham não durante a operação normal, mas <strong>durante inicialização parcial, falhas de periféricos, ordem incorreta de dependências ou estados indefinidos</strong>.</p>



<p class="wp-block-paragraph">Os padrões desta seção tornam o startup <strong>determinístico, auditável e recuperável</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.1 Startup Task (Task de Inicialização)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Inicialização espalhada entre <code>main()</code>, ISRs e tarefas diversas.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Criar uma <strong>tarefa exclusiva de startup</strong>, responsável por inicializar tudo <strong>em ordem controlada</strong>, antes do sistema entrar em operação normal.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Estrutura típica</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int main(void)
{
    HardwareInit();

    xTaskCreate(StartupTask, "Startup", 1024, NULL, tskIDLE_PRIORITY + 3, NULL);

    vTaskStartScheduler();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">int main(void)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    HardwareInit();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    xTaskCreate(StartupTask, &quot;Startup&quot;, 1024, NULL, tskIDLE_PRIORITY + 3, NULL);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    vTaskStartScheduler();</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void StartupTask(void *pvParameters)
{
    InitDrivers();
    InitServices();
    InitApplication();

    xTaskCreate(AppTask, "App", 1024, NULL, tskIDLE_PRIORITY + 1, NULL);

    vTaskDelete(NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void StartupTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    InitDrivers();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    InitServices();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    InitApplication();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    xTaskCreate(AppTask, &quot;App&quot;, 1024, NULL, tskIDLE_PRIORITY + 1, NULL);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    vTaskDelete(NULL);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Ordem explícita</li>



<li>Inicialização rastreável</li>



<li>Elimina “efeitos colaterais” no <code>main()</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Boa prática:</strong><br>Startup task deve <strong>se autodestruir</strong> após cumprir sua função.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.2 Init Sequencing (Sequenciamento de Inicialização)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Tarefas começam a rodar antes de suas dependências estarem prontas.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Inicialização ocorre em <strong>fases bem definidas</strong>, com sincronização explícita.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo com Event Groups</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#define EVT_DRIVERS_READY   (1 &lt;&lt; 0)
#define EVT_SERVICES_READY  (1 &lt;&lt; 1)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#define EVT_DRIVERS_READY   (1 &lt;&lt; 0)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#define EVT_SERVICES_READY  (1 &lt;&lt; 1)</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void StartupTask(void *pvParameters)
{
    InitDrivers();
    xEventGroupSetBits(systemEvents, EVT_DRIVERS_READY);

    InitServices();
    xEventGroupSetBits(systemEvents, EVT_SERVICES_READY);

    vTaskDelete(NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void StartupTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    InitDrivers();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xEventGroupSetBits(systemEvents, EVT_DRIVERS_READY);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    InitServices();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xEventGroupSetBits(systemEvents, EVT_SERVICES_READY);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    vTaskDelete(NULL);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void AppTask(void *pvParameters)
{
    xEventGroupWaitBits(
        systemEvents,
        EVT_DRIVERS_READY | EVT_SERVICES_READY,
        pdFALSE,
        pdTRUE,
        portMAX_DELAY
    );

    RunApplication();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void AppTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xEventGroupWaitBits(</span></span>
<span class="line"><span style="color: #D8DEE9FF">        systemEvents,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        EVT_DRIVERS_READY | EVT_SERVICES_READY,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        pdFALSE,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        pdTRUE,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        portMAX_DELAY</span></span>
<span class="line"><span style="color: #D8DEE9FF">    );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    RunApplication();</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagem:</strong><br>Dependências explícitas → menos bugs “fantasma”.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.3 Dependency Ordering Pattern</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Serviços que dependem implicitamente uns dos outros.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada serviço <strong>declara o que precisa</strong> antes de operar.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Exemplo conceitual</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>bool Network_IsReady(void);
bool Storage_IsReady(void);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">bool Network_IsReady(void);</span></span>
<span class="line"><span style="color: #D8DEE9FF">bool Storage_IsReady(void);</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void TelemetryTask(void *pvParameters)
{
    while (!Network_IsReady() || !Storage_IsReady())
    {
        vTaskDelay(pdMS_TO_TICKS(100));
    }

    StartTelemetry();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void TelemetryTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    while (!Network_IsReady() || !Storage_IsReady())</span></span>
<span class="line"><span style="color: #D8DEE9FF">    {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        vTaskDelay(pdMS_TO_TICKS(100));</span></span>
<span class="line"><span style="color: #D8DEE9FF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    StartTelemetry();</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Melhoria recomendada:</strong><br>Substituir polling por <strong>eventos ou notificações</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.4 Health Monitoring Pattern (Monitoramento de Saúde)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Tarefas travam silenciosamente.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada tarefa reporta periodicamente seu estado para um <strong>supervisor central</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">Estrutura básica</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
    uint32_t taskId;
    TickType_t lastAlive;
} TaskHealth;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">typedef struct {</span></span>
<span class="line"><span style="color: #D8DEE9FF">    uint32_t taskId;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    TickType_t lastAlive;</span></span>
<span class="line"><span style="color: #D8DEE9FF">} TaskHealth;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void HealthReport(uint32_t id)
{
    healthTable&#91;id&#93;.lastAlive = xTaskGetTickCount();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void HealthReport(uint32_t id)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    healthTable</span><span style="color: #ECEFF4">&#91;</span><span style="color: #88C0D0">id</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF">.lastAlive = xTaskGetTickCount();</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void SupervisorTask(void *pvParameters)
{
    for (;;)
    {
        if (TaskTimeoutDetected())
            EnterRecoveryMode();

        vTaskDelay(pdMS_TO_TICKS(500));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void SupervisorTask(void *pvParameters)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    for (;;)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        if (TaskTimeoutDetected())</span></span>
<span class="line"><span style="color: #D8DEE9FF">            EnterRecoveryMode();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        vTaskDelay(pdMS_TO_TICKS(500));</span></span>
<span class="line"><span style="color: #D8DEE9FF">    }</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Detecção precoce de falhas</li>



<li>Integração natural com watchdog</li>



<li>Essencial em sistemas remotos</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.5 Fail-Safe State Pattern</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Sistema entra em estado indefinido após falha grave.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Definir explicitamente um <strong>estado seguro</strong>, conhecido e controlado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void EnterSafeState(void)
{
    DisableOutputs();
    StopMotors();
    SignalErrorLED();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void EnterSafeState(void)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    DisableOutputs();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    StopMotors();</span></span>
<span class="line"><span style="color: #D8DEE9FF">    SignalErrorLED();</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Importante:</strong><br>Fail-safe <strong>não é reset</strong>. É sobrevivência controlada.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.6 Warm Restart vs Cold Restart</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Reset total desnecessário causa perda de estado e latência.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Diferenciar:</p>



<ul class="wp-block-list">
<li><strong>Cold restart</strong> → reboot completo</li>



<li><strong>Warm restart</strong> → reinicialização parcial de serviços</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>if (RecoverableFault())
    RestartServices();
else
    SystemReset();
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">if (RecoverableFault())</span></span>
<span class="line"><span style="color: #D8DEE9FF">    RestartServices();</span></span>
<span class="line"><span style="color: #D8DEE9FF">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">    SystemReset();</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7 – Síntese Geral e Checklist Arquitetural de Padrões para FreeRTOS</h2>



<p class="wp-block-paragraph">Após percorrer os principais grupos de padrões aplicáveis a sistemas com RTOS, fica claro que <strong>FreeRTOS não é apenas um escalonador</strong>, mas uma <strong>plataforma arquitetural</strong> que exige decisões conscientes desde o primeiro <code>xTaskCreate()</code>.</p>



<p class="wp-block-paragraph">Esta seção final transforma o conteúdo técnico em <strong>instrumento de uso real</strong>, algo que pode ser consultado durante o desenho ou revisão de um firmware.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.1 Mapa Conceitual dos Padrões em RTOS</h3>



<p class="wp-block-paragraph">Podemos organizar os padrões apresentados em <strong>camadas de decisão</strong>, do mais fundamental ao mais sistêmico:</p>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estrutura Básica</h3>



<ul class="wp-block-list">
<li>Superloop + Tasks</li>



<li>One Task per Responsibility</li>



<li>Cyclic Executive</li>



<li>Idle Task Pattern</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como o sistema respira</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comunicação e Sincronização</h3>



<ul class="wp-block-list">
<li>Event Queue</li>



<li>Mailbox</li>



<li>Publish–Subscribe</li>



<li>Task Notifications</li>



<li>Stream Buffer / Message Buffer</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como a informação flui</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Proteção de Recursos</h3>



<ul class="wp-block-list">
<li>Mutex com Priority Inheritance</li>



<li>Gatekeeper Task</li>



<li>Critical Sections</li>



<li>Event Groups</li>



<li>Deadlock Avoidance</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como o sistema se protege</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Controle de Comportamento</h3>



<ul class="wp-block-list">
<li>Finite State Machine (FSM)</li>



<li>Hierarchical State Machine (HSM)</li>



<li>Mode Manager</li>



<li>Recovery Pattern</li>



<li>Watchdog Pattern</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como o sistema se comporta e reage</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Arquitetura Interna</h3>



<ul class="wp-block-list">
<li>Layered Architecture</li>



<li>HAL</li>



<li>Service Layer</li>



<li>Active Object</li>



<li>Deferred Interrupt Processing</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como o sistema é construído</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Inicialização e Robustez</h3>



<ul class="wp-block-list">
<li>Startup Task</li>



<li>Init Sequencing</li>



<li>Dependency Ordering</li>



<li>Health Monitoring</li>



<li>Fail-Safe State</li>



<li>Warm vs Cold Restart</li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Define <strong>como o sistema nasce e sobrevive</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.2 Checklist Arquitetural para Projetos com FreeRTOS</h3>



<p class="wp-block-paragraph">Use este checklist como <strong>ferramenta de revisão técnica</strong>:</p>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estrutura</h4>



<ul class="wp-block-list">
<li>Cada tarefa tem uma responsabilidade clara?</li>



<li>Existe uma política clara de prioridades?</li>



<li>Tarefas críticas têm WCET conhecido?</li>
</ul>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comunicação</h4>



<ul class="wp-block-list">
<li>Variáveis globais foram substituídas por filas/eventos?</li>



<li>ISR apenas sinalizam, nunca processam?</li>



<li>Fluxos contínuos usam buffers, não filas?</li>
</ul>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Proteção</h4>



<ul class="wp-block-list">
<li>Mutexes são usados apenas para recursos?</li>



<li>Existe Gatekeeper para periféricos compartilhados?</li>



<li>Ordem de aquisição de recursos é consistente?</li>
</ul>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estados e Modos</h4>



<ul class="wp-block-list">
<li>O comportamento está modelado em FSM ou HSM?</li>



<li>Modos globais são explícitos?</li>



<li>Falhas são estados, não exceções implícitas?</li>
</ul>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Arquitetura</h4>



<ul class="wp-block-list">
<li>Aplicação não conhece registradores?</li>



<li>Drivers não conhecem RTOS?</li>



<li>Serviços encapsulam política e sincronização?</li>
</ul>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Inicialização e Saúde</h4>



<ul class="wp-block-list">
<li>Startup ocorre em task dedicada?</li>



<li>Dependências são explícitas?</li>



<li>Existe supervisão de tarefas?</li>



<li>Fail-safe é definido?</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.3 Erros Clássicos que Esses Padrões Evitam</h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> “Só mais um <code>volatile</code> resolve”</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> “Vamos proteger tudo com mutex”</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> “ISR rápida não precisa de cuidado”</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> “Reset resolve qualquer coisa”</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> “Depois a gente organiza a arquitetura”</li>
</ul>



<p class="wp-block-paragraph">Todos esses erros são <strong>sintomas da ausência de padrões</strong>, não de falta de RTOS.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Conclusão Geral do Artigo</h3>



<p class="wp-block-paragraph">A maturidade em sistemas embarcados com FreeRTOS <strong>não está em quantas tasks você cria</strong>, mas <strong>em como você estrutura comportamento, comunicação e recuperação</strong>.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>RTOS sem padrões é apenas concorrência.<br>RTOS com padrões é engenharia.</strong></p>
</blockquote>



<p class="wp-block-paragraph">Os padrões apresentados aqui não são teóricos: eles surgiram de <strong>sistemas industriais, médicos, automotivos e aeroespaciais</strong>, e quando aplicados corretamente, reduzem drasticamente:</p>



<ul class="wp-block-list">
<li>Bugs intermitentes</li>



<li>Tempo de depuração</li>



<li>Retrabalho arquitetural</li>



<li>Risco em produção</li>
</ul><p>The post <a href="https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/">Padrões de Projeto Aplicados a RTOS (FreeRTOS)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1206</post-id>	</item>
		<item>
		<title>Estratégia Profissional de Gestão de Código com Git em Projetos Individuais e em Equipe</title>
		<link>https://mcu.tec.br/geral/estrategia-profissional-de-gestao-de-codigo-com-git-em-projetos-individuais-e-em-equipe/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=estrategia-profissional-de-gestao-de-codigo-com-git-em-projetos-individuais-e-em-equipe</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 22:44:34 +0000</pubDate>
				<category><![CDATA[geral]]></category>
		<category><![CDATA[arquitetura de software]]></category>
		<category><![CDATA[boas práticas git]]></category>
		<category><![CDATA[controle de versão]]></category>
		<category><![CDATA[Engenharia de Software]]></category>
		<category><![CDATA[estratégia git]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[git branches]]></category>
		<category><![CDATA[git issues]]></category>
		<category><![CDATA[git para equipes]]></category>
		<category><![CDATA[git tags]]></category>
		<category><![CDATA[github workflow]]></category>
		<category><![CDATA[rastreabilidade de código]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[versionamento de código]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1417</guid>

					<description><![CDATA[<p>Aprenda uma estratégia profissional de uso do Git para projetos individuais e em equipe, com foco em organização de branches, uso avançado de tags, integração com issues no GitHub e boas práticas de arquitetura de software. Este guia detalhado aborda desde o controle de versões até a rastreabilidade completa do código, incluindo cenários com múltiplos repositórios e aplicações em sistemas embarcados com FreeRTOS, garantindo maior estabilidade, organização e produtividade no desenvolvimento.</p>
<p>The post <a href="https://mcu.tec.br/geral/estrategia-profissional-de-gestao-de-codigo-com-git-em-projetos-individuais-e-em-equipe/">Estratégia Profissional de Gestão de Código com Git em Projetos Individuais e em Equipe</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-yd4rg wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-yd4rg "><div class="eb-toc-container eb-toc-yd4rg  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Arquitetura de Branches: Main, Vers\u00f5es e Funcionalidades&quot;,&quot;text&quot;:&quot;Arquitetura de Branches: Main, Vers\u00f5es e Funcionalidades&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Cria\u00e7\u00e3o de Branches a partir do Main&quot;,&quot;text&quot;:&quot;Cria\u00e7\u00e3o de Branches a partir do Main&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Branch por Funcionalidade vs Branch por Vers\u00e3o&quot;,&quot;text&quot;:&quot;Branch por Funcionalidade vs Branch por Vers\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Mesclagem (Merge) com o Main&quot;,&quot;text&quot;:&quot;Mesclagem (Merge) com o Main&quot;,&quot;link&quot;:&quot;mesclagem-merge-com-o-main&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Atualiza\u00e7\u00e3o entre Vers\u00f5es em Paralelo&quot;,&quot;text&quot;:&quot;Atualiza\u00e7\u00e3o entre Vers\u00f5es em Paralelo&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Considera\u00e7\u00f5es Arquiteturais&quot;,&quot;text&quot;:&quot;Considera\u00e7\u00f5es Arquiteturais&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Uso de Tags para Controle de Vers\u00f5es, Eventos e Marcos do Projeto&quot;,&quot;text&quot;:&quot;Uso de Tags para Controle de Vers\u00f5es, Eventos e Marcos do Projeto&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Integra\u00e7\u00e3o com Issues e Rastreabilidade de Commits no GitHub&quot;,&quot;text&quot;:&quot;Integra\u00e7\u00e3o com Issues e Rastreabilidade de Commits no GitHub&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Branch vinculado \u00e0 Issue&quot;,&quot;text&quot;:&quot;Branch vinculado \u00e0 Issue&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Commits com refer\u00eancia \u00e0 Issue&quot;,&quot;text&quot;:&quot;Commits com refer\u00eancia \u00e0 Issue&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Uso combinado com Pull Requests&quot;,&quot;text&quot;:&quot;Uso combinado com Pull Requests&quot;,&quot;link&quot;:&quot;uso-combinado-com-pull-requests&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Rastreabilidade Completa&quot;,&quot;text&quot;:&quot;Rastreabilidade Completa&quot;,&quot;link&quot;:&quot;rastreabilidade-completa&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Integra\u00e7\u00e3o com Documenta\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Integra\u00e7\u00e3o com Documenta\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Considera\u00e7\u00f5es Avan\u00e7adas&quot;,&quot;text&quot;:&quot;Considera\u00e7\u00f5es Avan\u00e7adas&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Uso de Dois Reposit\u00f3rios: Ambiente de Desenvolvimento (origin_dev) e Produ\u00e7\u00e3o (origin)&quot;,&quot;text&quot;:&quot;Uso de Dois Reposit\u00f3rios: Ambiente de Desenvolvimento (origin_dev) e Produ\u00e7\u00e3o (origin)&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Estrutura Geral da Estrat\u00e9gia&quot;,&quot;text&quot;:&quot;Estrutura Geral da Estrat\u00e9gia&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Fluxo de Desenvolvimento no origin_dev&quot;,&quot;text&quot;:&quot;Fluxo de Desenvolvimento no origin_dev&quot;,&quot;link&quot;:&quot;fluxo-de-desenvolvimento-no-origin_dev&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Cria\u00e7\u00e3o do Branch de Vers\u00e3o&quot;,&quot;text&quot;:&quot;Cria\u00e7\u00e3o do Branch de Vers\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Valida\u00e7\u00e3o da Vers\u00e3o&quot;,&quot;text&quot;:&quot;Valida\u00e7\u00e3o da Vers\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Promo\u00e7\u00e3o para Produ\u00e7\u00e3o (origin)&quot;,&quot;text&quot;:&quot;Promo\u00e7\u00e3o para Produ\u00e7\u00e3o (origin)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Sincroniza\u00e7\u00e3o entre Ambientes&quot;,&quot;text&quot;:&quot;Sincroniza\u00e7\u00e3o entre Ambientes&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;An\u00e1lise Cr\u00edtica da Estrat\u00e9gia&quot;,&quot;text&quot;:&quot;An\u00e1lise Cr\u00edtica da Estrat\u00e9gia&quot;,&quot;link&quot;:&quot;eb-table-content-22&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Organiza\u00e7\u00e3o Arquitetural do C\u00f3digo e sua Rela\u00e7\u00e3o Direta com o Git&quot;,&quot;text&quot;:&quot;Organiza\u00e7\u00e3o Arquitetural do C\u00f3digo e sua Rela\u00e7\u00e3o Direta com o Git&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modulariza\u00e7\u00e3o como Estrat\u00e9gia de Versionamento&quot;,&quot;text&quot;:&quot;Modulariza\u00e7\u00e3o como Estrat\u00e9gia de Versionamento&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Isolamento de Responsabilidades&quot;,&quot;text&quot;:&quot;Isolamento de Responsabilidades&quot;,&quot;link&quot;:&quot;isolamento-de-responsabilidades&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Impacto Direto no Git&quot;,&quot;text&quot;:&quot;Impacto Direto no Git&quot;,&quot;link&quot;:&quot;impacto-direto-no-git&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Organiza\u00e7\u00e3o por Diret\u00f3rios e Contexto&quot;,&quot;text&quot;:&quot;Organiza\u00e7\u00e3o por Diret\u00f3rios e Contexto&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Rela\u00e7\u00e3o com Branches e Features&quot;,&quot;text&quot;:&quot;Rela\u00e7\u00e3o com Branches e Features&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Integra\u00e7\u00e3o com Testes e Valida\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Integra\u00e7\u00e3o com Testes e Valida\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-29&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Considera\u00e7\u00f5es Cr\u00edticas&quot;,&quot;text&quot;:&quot;Considera\u00e7\u00f5es Cr\u00edticas&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Arquitetura de Branches: Main, Vers\u00f5es e Funcionalidades&quot;,&quot;value&quot;:&quot;arquitetura-de-branches-main-vers\u00f5es-e-funcionalidades&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Cria\u00e7\u00e3o de Branches a partir do Main&quot;,&quot;value&quot;:&quot;cria\u00e7\u00e3o-de-branches-a-partir-do-main&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Branch por Funcionalidade vs Branch por Vers\u00e3o&quot;,&quot;value&quot;:&quot;branch-por-funcionalidade-vs-branch-por-vers\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Mesclagem (Merge) com o Main&quot;,&quot;value&quot;:&quot;mesclagem-merge-com-o-main&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Atualiza\u00e7\u00e3o entre Vers\u00f5es em Paralelo&quot;,&quot;value&quot;:&quot;atualiza\u00e7\u00e3o-entre-vers\u00f5es-em-paralelo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Considera\u00e7\u00f5es Arquiteturais&quot;,&quot;value&quot;:&quot;considera\u00e7\u00f5es-arquiteturais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso de Tags para Controle de Vers\u00f5es, Eventos e Marcos do Projeto&quot;,&quot;value&quot;:&quot;uso-de-tags-para-controle-de-vers\u00f5es-eventos-e-marcos-do-projeto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Integra\u00e7\u00e3o com Issues e Rastreabilidade de Commits no GitHub&quot;,&quot;value&quot;:&quot;integra\u00e7\u00e3o-com-issues-e-rastreabilidade-de-commits-no-github&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Branch vinculado \u00e0 Issue&quot;,&quot;value&quot;:&quot;branch-vinculado-\u00e0-issue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Commits com refer\u00eancia \u00e0 Issue&quot;,&quot;value&quot;:&quot;commits-com-refer\u00eancia-\u00e0-issue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso combinado com Pull Requests&quot;,&quot;value&quot;:&quot;uso-combinado-com-pull-requests&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Rastreabilidade Completa&quot;,&quot;value&quot;:&quot;rastreabilidade-completa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Integra\u00e7\u00e3o com Documenta\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;integra\u00e7\u00e3o-com-documenta\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Considera\u00e7\u00f5es Avan\u00e7adas&quot;,&quot;value&quot;:&quot;considera\u00e7\u00f5es-avan\u00e7adas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso de Dois Reposit\u00f3rios: Ambiente de Desenvolvimento (origin_dev) e Produ\u00e7\u00e3o (origin)&quot;,&quot;value&quot;:&quot;uso-de-dois-reposit\u00f3rios-ambiente-de-desenvolvimento-origin_dev-e-produ\u00e7\u00e3o-origin&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrutura Geral da Estrat\u00e9gia&quot;,&quot;value&quot;:&quot;estrutura-geral-da-estrat\u00e9gia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Fluxo de Desenvolvimento no origin_dev&quot;,&quot;value&quot;:&quot;fluxo-de-desenvolvimento-no-origin_dev&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Cria\u00e7\u00e3o do Branch de Vers\u00e3o&quot;,&quot;value&quot;:&quot;cria\u00e7\u00e3o-do-branch-de-vers\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Valida\u00e7\u00e3o da Vers\u00e3o&quot;,&quot;value&quot;:&quot;valida\u00e7\u00e3o-da-vers\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Promo\u00e7\u00e3o para Produ\u00e7\u00e3o (origin)&quot;,&quot;value&quot;:&quot;promo\u00e7\u00e3o-para-produ\u00e7\u00e3o-origin&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Sincroniza\u00e7\u00e3o entre Ambientes&quot;,&quot;value&quot;:&quot;sincroniza\u00e7\u00e3o-entre-ambientes&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;An\u00e1lise Cr\u00edtica da Estrat\u00e9gia&quot;,&quot;value&quot;:&quot;an\u00e1lise-cr\u00edtica-da-estrat\u00e9gia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Organiza\u00e7\u00e3o Arquitetural do C\u00f3digo e sua Rela\u00e7\u00e3o Direta com o Git&quot;,&quot;value&quot;:&quot;organiza\u00e7\u00e3o-arquitetural-do-c\u00f3digo-e-sua-rela\u00e7\u00e3o-direta-com-o-git&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modulariza\u00e7\u00e3o como Estrat\u00e9gia de Versionamento&quot;,&quot;value&quot;:&quot;modulariza\u00e7\u00e3o-como-estrat\u00e9gia-de-versionamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Isolamento de Responsabilidades&quot;,&quot;value&quot;:&quot;isolamento-de-responsabilidades&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Impacto Direto no Git&quot;,&quot;value&quot;:&quot;impacto-direto-no-git&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Organiza\u00e7\u00e3o por Diret\u00f3rios e Contexto&quot;,&quot;value&quot;:&quot;organiza\u00e7\u00e3o-por-diret\u00f3rios-e-contexto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Rela\u00e7\u00e3o com Branches e Features&quot;,&quot;value&quot;:&quot;rela\u00e7\u00e3o-com-branches-e-features&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Integra\u00e7\u00e3o com Testes e Valida\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;integra\u00e7\u00e3o-com-testes-e-valida\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Considera\u00e7\u00f5es Cr\u00edticas&quot;,&quot;value&quot;:&quot;considera\u00e7\u00f5es-cr\u00edticas&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução</a><li><a href="#eb-table-content-1">Arquitetura de Branches: Main, Versões e Funcionalidades</a><ul class="eb-toc__list"><li><a href="#eb-table-content-2">Criação de Branches a partir do Main</a><li><a href="#eb-table-content-3">Branch por Funcionalidade vs Branch por Versão</a><li><a href="#mesclagem-merge-com-o-main">Mesclagem (Merge) com o Main</a><li><a href="#eb-table-content-5">Atualização entre Versões em Paralelo</a><li><a href="#eb-table-content-6">Considerações Arquiteturais</a></li></ul><li><a href="#eb-table-content-7">Uso de Tags para Controle de Versões, Eventos e Marcos do Projeto</a><li><a href="#eb-table-content-8">Integração com Issues e Rastreabilidade de Commits no GitHub</a><ul class="eb-toc__list"><li><a href="#eb-table-content-9">Branch vinculado à Issue</a><li><a href="#eb-table-content-10">Commits com referência à Issue</a><li><a href="#uso-combinado-com-pull-requests">Uso combinado com Pull Requests</a><li><a href="#rastreabilidade-completa">Rastreabilidade Completa</a><li><a href="#eb-table-content-13">Integração com Documentação</a><li><a href="#eb-table-content-14">Considerações Avançadas</a></li></ul><li><a href="#eb-table-content-15">Uso de Dois Repositórios: Ambiente de Desenvolvimento (origin_dev) e Produção (origin)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-16">Estrutura Geral da Estratégia</a><li><a href="#fluxo-de-desenvolvimento-no-origin_dev">Fluxo de Desenvolvimento no origin_dev</a><li><a href="#eb-table-content-18">Criação do Branch de Versão</a><li><a href="#eb-table-content-19">Validação da Versão</a><li><a href="#eb-table-content-20">Promoção para Produção (origin)</a><li><a href="#eb-table-content-21">Sincronização entre Ambientes</a><li><a href="#eb-table-content-22">Análise Crítica da Estratégia</a></li></ul><li><a href="#eb-table-content-23">Organização Arquitetural do Código e sua Relação Direta com o Git</a><ul class="eb-toc__list"><li><a href="#eb-table-content-24">Modularização como Estratégia de Versionamento</a><li><a href="#isolamento-de-responsabilidades">Isolamento de Responsabilidades</a><li><a href="#impacto-direto-no-git">Impacto Direto no Git</a><li><a href="#eb-table-content-27">Organização por Diretórios e Contexto</a><li><a href="#eb-table-content-28">Relação com Branches e Features</a><li><a href="#eb-table-content-29">Integração com Testes e Validação</a><li><a href="#eb-table-content-30">Considerações Críticas</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading">Introdução</h2>



<p class="wp-block-paragraph">O <strong>Git</strong> tornou-se o sistema de controle de versão mais utilizado no desenvolvimento de software moderno. Ele permite que desenvolvedores acompanhem alterações no código, trabalhem em equipe de forma organizada e mantenham histórico detalhado de todas as modificações realizadas em um projeto. No entanto, embora o Git ofereça um conjunto poderoso de ferramentas, seu uso eficaz depende muito da <strong>estratégia adotada pela equipe ou pelo desenvolvedor</strong>.</p>



<p class="wp-block-paragraph">Em muitos projetos, especialmente aqueles relacionados a <strong>sistemas embarcados, firmware e aplicações críticas</strong>, como os que envolvem microcontroladores, RTOS ou arquiteturas distribuídas, a forma como o código é organizado dentro do Git pode impactar diretamente na <strong>qualidade do software, na rastreabilidade das mudanças e na capacidade de manutenção do projeto ao longo do tempo</strong>.</p>



<p class="wp-block-paragraph">Uma estratégia bem definida de uso do Git permite resolver diversos problemas comuns no desenvolvimento colaborativo. Entre esses problemas estão conflitos frequentes de código, dificuldade em identificar quando uma funcionalidade foi introduzida, ausência de rastreabilidade entre commits e tarefas de desenvolvimento, e dificuldades para manter versões estáveis do software enquanto novas funcionalidades continuam sendo implementadas.</p>



<p class="wp-block-paragraph">Ao longo da experiência prática em projetos individuais e também em equipes dentro de empresas, desenvolvi uma abordagem de organização baseada em <strong>branches de versões, branches de funcionalidades, uso disciplinado de tags e integração com sistemas de issues</strong>, especialmente no GitHub. Essa abordagem busca equilibrar três aspectos fundamentais do desenvolvimento moderno: <strong>estabilidade da versão em produção, evolução contínua do software e rastreabilidade completa das alterações realizadas</strong>.</p>



<p class="wp-block-paragraph">Além disso, essa estratégia também considera cenários mais complexos de desenvolvimento, como ambientes onde existem <strong>dois repositórios distintos — um para desenvolvimento e outro para produção — e também a necessidade de manter simultaneamente múltiplas versões do software</strong>, algo comum em produtos embarcados que permanecem anos no mercado recebendo atualizações incrementais.</p>



<p class="wp-block-paragraph">Neste artigo será apresentada, de forma didática e detalhada, uma estratégia prática de organização de projetos com Git, incluindo o uso de <strong>branches, tags, commits estruturados, integração com issues e organização arquitetural do código</strong>. Também serão apresentados os comandos fundamentais do Git necessários para implementar essa estratégia no dia a dia do desenvolvimento.</p>



<p class="wp-block-paragraph">O objetivo não é apenas explicar os comandos, mas mostrar <strong>como construir um fluxo de trabalho que permita manter o projeto organizado, escalável e rastreável</strong>, mesmo em projetos grandes ou em equipes distribuídas.</p>



<p class="wp-block-paragraph">Na próxima seção será apresentada a base dessa estratégia: <strong>a organização do repositório a partir do branch principal (Main) e a criação de branches para versões e funcionalidades</strong>.</p><p>The post <a href="https://mcu.tec.br/geral/estrategia-profissional-de-gestao-de-codigo-com-git-em-projetos-individuais-e-em-equipe/">Estratégia Profissional de Gestão de Código com Git em Projetos Individuais e em Equipe</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1417</post-id>	</item>
		<item>
		<title>Padrões de Projeto Aplicados a RTOS (FreeRTOS)</title>
		<link>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=padroes-de-projeto-aplicados-a-rtos-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 13 Mar 2026 15:48:51 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura de firmware]]></category>
		<category><![CDATA[comunicação entre tarefas FreeRTOS]]></category>
		<category><![CDATA[firmware robusto]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[inicialização em RTOS]]></category>
		<category><![CDATA[máquinas de estado em FreeRTOS]]></category>
		<category><![CDATA[mutex e gatekeeper FreeRTOS]]></category>
		<category><![CDATA[padrões de projeto embarcados]]></category>
		<category><![CDATA[RTOS em sistemas embarcados]]></category>
		<category><![CDATA[sistemas de tempo real]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1198</guid>

					<description><![CDATA[<p>Neste artigo apresentamos, de forma didática e aprofundada, os principais padrões de projeto aplicados a sistemas embarcados com FreeRTOS. O conteúdo aborda desde a estruturação de tarefas, comunicação e sincronização, proteção de recursos e controle de estados, até arquitetura em camadas, inicialização segura e monitoramento de saúde do sistema. Com exemplos práticos em C e foco em aplicações reais, o artigo mostra como usar padrões para construir firmware robusto, previsível e escalável, adequado a ambientes industriais, IoT e sistemas críticos de tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos/">Padrões de Projeto Aplicados a RTOS (FreeRTOS)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-n0zji wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-n0zji "><div class="eb-toc-container eb-toc-n0zji  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o geral&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o geral&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es Fundamentais de Estrutura\u00e7\u00e3o de Tarefas&quot;,&quot;text&quot;:&quot;Padr\u00f5es Fundamentais de Estrutura\u00e7\u00e3o de Tarefas&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.1 Superloop + Tasks (Incremental RTOS Adoption)&quot;,&quot;text&quot;:&quot;1.1 Superloop + Tasks (Incremental RTOS Adoption)&quot;,&quot;link&quot;:&quot;11-superloop-tasks-incremental-rtos-adoption&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)&quot;,&quot;text&quot;:&quot;1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)&quot;,&quot;link&quot;:&quot;12-one-task-per-responsibility-uma-tarefa-por-responsabilidade&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.3 Cyclic Executive com RTOS&quot;,&quot;text&quot;:&quot;1.3 Cyclic Executive com RTOS&quot;,&quot;link&quot;:&quot;13-cyclic-executive-com-rtos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.4 Idle Task como Padr\u00e3o Arquitetural&quot;,&quot;text&quot;:&quot;1.4 Idle Task como Padr\u00e3o Arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o em RTOS&quot;,&quot;text&quot;:&quot;Padr\u00f5es de Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o em RTOS&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 Event Queue (Fila de Eventos)&quot;,&quot;text&quot;:&quot;2.1 Event Queue (Fila de Eventos)&quot;,&quot;link&quot;:&quot;21-event-queue-fila-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 Mailbox (Fila de Mensagem \u00danica)&quot;,&quot;text&quot;:&quot;2.2 Mailbox (Fila de Mensagem \u00danica)&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 Publish\u2013Subscribe (Pub-Sub) com FreeRTOS&quot;,&quot;text&quot;:&quot;2.3 Publish\u2013Subscribe (Pub-Sub) com FreeRTOS&quot;,&quot;link&quot;:&quot;23-publishsubscribe-pub-sub-com-freertos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 Task Notification como Padr\u00e3o de Sinaliza\u00e7\u00e3o R\u00e1pida&quot;,&quot;text&quot;:&quot;2.4 Task Notification como Padr\u00e3o de Sinaliza\u00e7\u00e3o R\u00e1pida&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.5 Stream Buffer e Message Buffer&quot;,&quot;text&quot;:&quot;2.5 Stream Buffer e Message Buffer&quot;,&quot;link&quot;:&quot;25-stream-buffer-e-message-buffer&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Stream Buffer&quot;,&quot;text&quot;:&quot;Stream Buffer&quot;,&quot;link&quot;:&quot;stream-buffer&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Message Buffer&quot;,&quot;text&quot;:&quot;Message Buffer&quot;,&quot;link&quot;:&quot;message-buffer&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de Exclus\u00e3o M\u00fatua, Prote\u00e7\u00e3o de Recursos e Preven\u00e7\u00e3o de Deadlock&quot;,&quot;text&quot;:&quot;Padr\u00f5es de Exclus\u00e3o M\u00fatua, Prote\u00e7\u00e3o de Recursos e Preven\u00e7\u00e3o de Deadlock&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 Mutex com Priority Inheritance&quot;,&quot;text&quot;:&quot;3.1 Mutex com Priority Inheritance&quot;,&quot;link&quot;:&quot;31-mutex-com-priority-inheritance&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Gatekeeper Task (Padr\u00e3o Fundamental em FreeRTOS)&quot;,&quot;text&quot;:&quot;3.2 Gatekeeper Task (Padr\u00e3o Fundamental em FreeRTOS)&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Critical Section (Uso cir\u00fargico)&quot;,&quot;text&quot;:&quot;3.3 Critical Section (Uso cir\u00fargico)&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 Read\u2013Modify\u2013Write protegido (Anti-pattern cl\u00e1ssico)&quot;,&quot;text&quot;:&quot;3.4 Read\u2013Modify\u2013Write protegido (Anti-pattern cl\u00e1ssico)&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Event Groups como Padr\u00e3o de Coordena\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;3.5 Event Groups como Padr\u00e3o de Coordena\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Deadlock Avoidance (Padr\u00f5es de Preven\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;3.6 Deadlock Avoidance (Padr\u00f5es de Preven\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de Controle de Fluxo, Estados e Recupera\u00e7\u00e3o em RTOS&quot;,&quot;text&quot;:&quot;Padr\u00f5es de Controle de Fluxo, Estados e Recupera\u00e7\u00e3o em RTOS&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 State Machine (M\u00e1quina de Estados Finita \u2013 FSM)&quot;,&quot;text&quot;:&quot;4.1 State Machine (M\u00e1quina de Estados Finita \u2013 FSM)&quot;,&quot;link&quot;:&quot;eb-table-content-22&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;text&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Execu\u00e7\u00e3o da m\u00e1quina de estados (task dedicada)&quot;,&quot;text&quot;:&quot;Execu\u00e7\u00e3o da m\u00e1quina de estados (task dedicada)&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Hierarchical State Machine (HSM)&quot;,&quot;text&quot;:&quot;4.2 Hierarchical State Machine (HSM)&quot;,&quot;link&quot;:&quot;42-hierarchical-state-machine-hsm&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo conceitual&quot;,&quot;text&quot;:&quot;Exemplo conceitual&quot;,&quot;link&quot;:&quot;exemplo-conceitual&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Implementa\u00e7\u00e3o simplificada em C&quot;,&quot;text&quot;:&quot;Implementa\u00e7\u00e3o simplificada em C&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Mode Manager (Gerenciador de Modos)&quot;,&quot;text&quot;:&quot;4.3 Mode Manager (Gerenciador de Modos)&quot;,&quot;link&quot;:&quot;43-mode-manager-gerenciador-de-modos&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Modos t\u00edpicos&quot;,&quot;text&quot;:&quot;Modos t\u00edpicos&quot;,&quot;link&quot;:&quot;eb-table-content-29&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Mode Manager&quot;,&quot;text&quot;:&quot;Mode Manager&quot;,&quot;link&quot;:&quot;mode-manager&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Uso pelas tarefas&quot;,&quot;text&quot;:&quot;Uso pelas tarefas&quot;,&quot;link&quot;:&quot;uso-pelas-tarefas&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Recovery Pattern (Padr\u00e3o de Recupera\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;4.4 Recovery Pattern (Padr\u00e3o de Recupera\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo de recupera\u00e7\u00e3o controlada&quot;,&quot;text&quot;:&quot;Exemplo de recupera\u00e7\u00e3o controlada&quot;,&quot;link&quot;:&quot;eb-table-content-33&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Watchdog como Padr\u00e3o Arquitetural&quot;,&quot;text&quot;:&quot;4.5 Watchdog como Padr\u00e3o Arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de Arquitetura em Camadas, Drivers e Servi\u00e7os em RTOS&quot;,&quot;text&quot;:&quot;Padr\u00f5es de Arquitetura em Camadas, Drivers e Servi\u00e7os em RTOS&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Layered Architecture (Arquitetura em Camadas)&quot;,&quot;text&quot;:&quot;5.1 Layered Architecture (Arquitetura em Camadas)&quot;,&quot;link&quot;:&quot;51-layered-architecture-arquitetura-em-camadas&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Camadas t\u00edpicas em FreeRTOS&quot;,&quot;text&quot;:&quot;Camadas t\u00edpicas em FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-37&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo de separa\u00e7\u00e3o correta&quot;,&quot;text&quot;:&quot;Exemplo de separa\u00e7\u00e3o correta&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Hardware Abstraction Layer (HAL) como Padr\u00e3o&quot;,&quot;text&quot;:&quot;5.2 Hardware Abstraction Layer (HAL) como Padr\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Service Layer (Camada de Servi\u00e7os)&quot;,&quot;text&quot;:&quot;5.3 Service Layer (Camada de Servi\u00e7os)&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo: Servi\u00e7o de UART com Gatekeeper&quot;,&quot;text&quot;:&quot;Exemplo: Servi\u00e7o de UART com Gatekeeper&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Active Object Pattern&quot;,&quot;text&quot;:&quot;5.4 Active Object Pattern&quot;,&quot;link&quot;:&quot;54-active-object-pattern&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Estrutura conceitual&quot;,&quot;text&quot;:&quot;Estrutura conceitual&quot;,&quot;link&quot;:&quot;estrutura-conceitual&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo simplificado&quot;,&quot;text&quot;:&quot;Exemplo simplificado&quot;,&quot;link&quot;:&quot;exemplo-simplificado&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Deferred Interrupt Processing&quot;,&quot;text&quot;:&quot;5.5 Deferred Interrupt Processing&quot;,&quot;link&quot;:&quot;55-deferred-interrupt-processing&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de Inicializa\u00e7\u00e3o, Startup Sequencial e Monitoramento de Sa\u00fade&quot;,&quot;text&quot;:&quot;Padr\u00f5es de Inicializa\u00e7\u00e3o, Startup Sequencial e Monitoramento de Sa\u00fade&quot;,&quot;link&quot;:&quot;eb-table-content-46&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 Startup Task (Task de Inicializa\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;6.1 Startup Task (Task de Inicializa\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-47&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Estrutura t\u00edpica&quot;,&quot;text&quot;:&quot;Estrutura t\u00edpica&quot;,&quot;link&quot;:&quot;eb-table-content-48&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Init Sequencing (Sequenciamento de Inicializa\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;6.2 Init Sequencing (Sequenciamento de Inicializa\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-49&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo com Event Groups&quot;,&quot;text&quot;:&quot;Exemplo com Event Groups&quot;,&quot;link&quot;:&quot;exemplo-com-event-groups&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Dependency Ordering Pattern&quot;,&quot;text&quot;:&quot;6.3 Dependency Ordering Pattern&quot;,&quot;link&quot;:&quot;63-dependency-ordering-pattern&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo conceitual&quot;,&quot;text&quot;:&quot;Exemplo conceitual&quot;,&quot;link&quot;:&quot;exemplo-conceitual&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 Health Monitoring Pattern (Monitoramento de Sa\u00fade)&quot;,&quot;text&quot;:&quot;6.4 Health Monitoring Pattern (Monitoramento de Sa\u00fade)&quot;,&quot;link&quot;:&quot;eb-table-content-53&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;text&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;link&quot;:&quot;eb-table-content-54&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.5 Fail-Safe State Pattern&quot;,&quot;text&quot;:&quot;6.5 Fail-Safe State Pattern&quot;,&quot;link&quot;:&quot;65-fail-safe-state-pattern&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.6 Warm Restart vs Cold Restart&quot;,&quot;text&quot;:&quot;6.6 Warm Restart vs Cold Restart&quot;,&quot;link&quot;:&quot;66-warm-restart-vs-cold-restart&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;S\u00edntese Geral e Checklist Arquitetural de Padr\u00f5es para FreeRTOS&quot;,&quot;text&quot;:&quot;S\u00edntese Geral e Checklist Arquitetural de Padr\u00f5es para FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-57&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.1 Mapa Conceitual dos Padr\u00f5es em RTOS&quot;,&quot;text&quot;:&quot;7.1 Mapa Conceitual dos Padr\u00f5es em RTOS&quot;,&quot;link&quot;:&quot;eb-table-content-58&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Estrutura B\u00e1sica&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Estrutura B\u00e1sica&quot;,&quot;link&quot;:&quot;eb-table-content-59&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-60&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Prote\u00e7\u00e3o de Recursos&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Prote\u00e7\u00e3o de Recursos&quot;,&quot;link&quot;:&quot;eb-table-content-61&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Controle de Comportamento&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Controle de Comportamento&quot;,&quot;link&quot;:&quot;eb-table-content-62&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Arquitetura Interna&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Arquitetura Interna&quot;,&quot;link&quot;:&quot;eb-table-content-63&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;\ud83d\udd39 Inicializa\u00e7\u00e3o e Robustez&quot;,&quot;text&quot;:&quot;\ud83d\udd39 Inicializa\u00e7\u00e3o e Robustez&quot;,&quot;link&quot;:&quot;eb-table-content-64&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.2 Checklist Arquitetural para Projetos com FreeRTOS&quot;,&quot;text&quot;:&quot;7.2 Checklist Arquitetural para Projetos com FreeRTOS&quot;,&quot;link&quot;:&quot;72-checklist-arquitetural-para-projetos-com-freertos&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Estrutura&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Estrutura&quot;,&quot;link&quot;:&quot;eb-table-content-66&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Comunica\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Comunica\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-67&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Prote\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Prote\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-68&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Estados e Modos&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Estados e Modos&quot;,&quot;link&quot;:&quot;eb-table-content-69&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Arquitetura&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Arquitetura&quot;,&quot;link&quot;:&quot;eb-table-content-70&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;\u2714\ufe0f Inicializa\u00e7\u00e3o e Sa\u00fade&quot;,&quot;text&quot;:&quot;\u2714\ufe0f Inicializa\u00e7\u00e3o e Sa\u00fade&quot;,&quot;link&quot;:&quot;eb-table-content-71&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.3 Erros Cl\u00e1ssicos que Esses Padr\u00f5es Evitam&quot;,&quot;text&quot;:&quot;7.3 Erros Cl\u00e1ssicos que Esses Padr\u00f5es Evitam&quot;,&quot;link&quot;:&quot;eb-table-content-72&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Conclus\u00e3o&quot;,&quot;text&quot;:&quot;Conclus\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-73&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o geral&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-geral&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es Fundamentais de Estrutura\u00e7\u00e3o de Tarefas&quot;,&quot;value&quot;:&quot;padr\u00f5es-fundamentais-de-estrutura\u00e7\u00e3o-de-tarefas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.1 Superloop + Tasks (Incremental RTOS Adoption)&quot;,&quot;value&quot;:&quot;11-superloop-tasks-incremental-rtos-adoption&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)&quot;,&quot;value&quot;:&quot;12-one-task-per-responsibility-uma-tarefa-por-responsabilidade&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.3 Cyclic Executive com RTOS&quot;,&quot;value&quot;:&quot;13-cyclic-executive-com-rtos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.4 Idle Task como Padr\u00e3o Arquitetural&quot;,&quot;value&quot;:&quot;14-idle-task-como-padr\u00e3o-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o em RTOS&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-comunica\u00e7\u00e3o-e-sincroniza\u00e7\u00e3o-em-rtos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 Event Queue (Fila de Eventos)&quot;,&quot;value&quot;:&quot;21-event-queue-fila-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 Mailbox (Fila de Mensagem \u00danica)&quot;,&quot;value&quot;:&quot;22-mailbox-fila-de-mensagem-\u00fanica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 Publish\u2013Subscribe (Pub-Sub) com FreeRTOS&quot;,&quot;value&quot;:&quot;23-publishsubscribe-pub-sub-com-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 Task Notification como Padr\u00e3o de Sinaliza\u00e7\u00e3o R\u00e1pida&quot;,&quot;value&quot;:&quot;24-task-notification-como-padr\u00e3o-de-sinaliza\u00e7\u00e3o-r\u00e1pida&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.5 Stream Buffer e Message Buffer&quot;,&quot;value&quot;:&quot;25-stream-buffer-e-message-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffer&quot;,&quot;value&quot;:&quot;stream-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Message Buffer&quot;,&quot;value&quot;:&quot;message-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de Exclus\u00e3o M\u00fatua, Prote\u00e7\u00e3o de Recursos e Preven\u00e7\u00e3o de Deadlock&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-exclus\u00e3o-m\u00fatua-prote\u00e7\u00e3o-de-recursos-e-preven\u00e7\u00e3o-de-deadlock&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 Mutex com Priority Inheritance&quot;,&quot;value&quot;:&quot;31-mutex-com-priority-inheritance&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Gatekeeper Task (Padr\u00e3o Fundamental em FreeRTOS)&quot;,&quot;value&quot;:&quot;32-gatekeeper-task-padr\u00e3o-fundamental-em-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Critical Section (Uso cir\u00fargico)&quot;,&quot;value&quot;:&quot;33-critical-section-uso-cir\u00fargico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 Read\u2013Modify\u2013Write protegido (Anti-pattern cl\u00e1ssico)&quot;,&quot;value&quot;:&quot;34-readmodifywrite-protegido-anti-pattern-cl\u00e1ssico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Event Groups como Padr\u00e3o de Coordena\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;35-event-groups-como-padr\u00e3o-de-coordena\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Deadlock Avoidance (Padr\u00f5es de Preven\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;36-deadlock-avoidance-padr\u00f5es-de-preven\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de Controle de Fluxo, Estados e Recupera\u00e7\u00e3o em RTOS&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-controle-de-fluxo-estados-e-recupera\u00e7\u00e3o-em-rtos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 State Machine (M\u00e1quina de Estados Finita \u2013 FSM)&quot;,&quot;value&quot;:&quot;41-state-machine-m\u00e1quina-de-estados-finita-fsm&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;value&quot;:&quot;estrutura-b\u00e1sica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Execu\u00e7\u00e3o da m\u00e1quina de estados (task dedicada)&quot;,&quot;value&quot;:&quot;execu\u00e7\u00e3o-da-m\u00e1quina-de-estados-task-dedicada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Hierarchical State Machine (HSM)&quot;,&quot;value&quot;:&quot;42-hierarchical-state-machine-hsm&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo conceitual&quot;,&quot;value&quot;:&quot;exemplo-conceitual&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implementa\u00e7\u00e3o simplificada em C&quot;,&quot;value&quot;:&quot;implementa\u00e7\u00e3o-simplificada-em-c&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Mode Manager (Gerenciador de Modos)&quot;,&quot;value&quot;:&quot;43-mode-manager-gerenciador-de-modos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modos t\u00edpicos&quot;,&quot;value&quot;:&quot;modos-t\u00edpicos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Mode Manager&quot;,&quot;value&quot;:&quot;mode-manager&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso pelas tarefas&quot;,&quot;value&quot;:&quot;uso-pelas-tarefas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Recovery Pattern (Padr\u00e3o de Recupera\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;44-recovery-pattern-padr\u00e3o-de-recupera\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de recupera\u00e7\u00e3o controlada&quot;,&quot;value&quot;:&quot;exemplo-de-recupera\u00e7\u00e3o-controlada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Watchdog como Padr\u00e3o Arquitetural&quot;,&quot;value&quot;:&quot;45-watchdog-como-padr\u00e3o-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de Arquitetura em Camadas, Drivers e Servi\u00e7os em RTOS&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-arquitetura-em-camadas-drivers-e-servi\u00e7os-em-rtos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Layered Architecture (Arquitetura em Camadas)&quot;,&quot;value&quot;:&quot;51-layered-architecture-arquitetura-em-camadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Camadas t\u00edpicas em FreeRTOS&quot;,&quot;value&quot;:&quot;camadas-t\u00edpicas-em-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de separa\u00e7\u00e3o correta&quot;,&quot;value&quot;:&quot;exemplo-de-separa\u00e7\u00e3o-correta&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Hardware Abstraction Layer (HAL) como Padr\u00e3o&quot;,&quot;value&quot;:&quot;52-hardware-abstraction-layer-hal-como-padr\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Service Layer (Camada de Servi\u00e7os)&quot;,&quot;value&quot;:&quot;53-service-layer-camada-de-servi\u00e7os&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo: Servi\u00e7o de UART com Gatekeeper&quot;,&quot;value&quot;:&quot;exemplo-servi\u00e7o-de-uart-com-gatekeeper&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Active Object Pattern&quot;,&quot;value&quot;:&quot;54-active-object-pattern&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrutura conceitual&quot;,&quot;value&quot;:&quot;estrutura-conceitual&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo simplificado&quot;,&quot;value&quot;:&quot;exemplo-simplificado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Deferred Interrupt Processing&quot;,&quot;value&quot;:&quot;55-deferred-interrupt-processing&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de Inicializa\u00e7\u00e3o, Startup Sequencial e Monitoramento de Sa\u00fade&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-inicializa\u00e7\u00e3o-startup-sequencial-e-monitoramento-de-sa\u00fade&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 Startup Task (Task de Inicializa\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;61-startup-task-task-de-inicializa\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrutura t\u00edpica&quot;,&quot;value&quot;:&quot;estrutura-t\u00edpica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Init Sequencing (Sequenciamento de Inicializa\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;62-init-sequencing-sequenciamento-de-inicializa\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo com Event Groups&quot;,&quot;value&quot;:&quot;exemplo-com-event-groups&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Dependency Ordering Pattern&quot;,&quot;value&quot;:&quot;63-dependency-ordering-pattern&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo conceitual&quot;,&quot;value&quot;:&quot;exemplo-conceitual&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 Health Monitoring Pattern (Monitoramento de Sa\u00fade)&quot;,&quot;value&quot;:&quot;64-health-monitoring-pattern-monitoramento-de-sa\u00fade&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrutura b\u00e1sica&quot;,&quot;value&quot;:&quot;estrutura-b\u00e1sica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.5 Fail-Safe State Pattern&quot;,&quot;value&quot;:&quot;65-fail-safe-state-pattern&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.6 Warm Restart vs Cold Restart&quot;,&quot;value&quot;:&quot;66-warm-restart-vs-cold-restart&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;S\u00edntese Geral e Checklist Arquitetural de Padr\u00f5es para FreeRTOS&quot;,&quot;value&quot;:&quot;s\u00edntese-geral-e-checklist-arquitetural-de-padr\u00f5es-para-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.1 Mapa Conceitual dos Padr\u00f5es em RTOS&quot;,&quot;value&quot;:&quot;71-mapa-conceitual-dos-padr\u00f5es-em-rtos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Estrutura B\u00e1sica&quot;,&quot;value&quot;:&quot;\ud83d\udd39-estrutura-b\u00e1sica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Comunica\u00e7\u00e3o e Sincroniza\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;\ud83d\udd39-comunica\u00e7\u00e3o-e-sincroniza\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Prote\u00e7\u00e3o de Recursos&quot;,&quot;value&quot;:&quot;\ud83d\udd39-prote\u00e7\u00e3o-de-recursos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Controle de Comportamento&quot;,&quot;value&quot;:&quot;\ud83d\udd39-controle-de-comportamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Arquitetura Interna&quot;,&quot;value&quot;:&quot;\ud83d\udd39-arquitetura-interna&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\ud83d\udd39 Inicializa\u00e7\u00e3o e Robustez&quot;,&quot;value&quot;:&quot;\ud83d\udd39-inicializa\u00e7\u00e3o-e-robustez&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.2 Checklist Arquitetural para Projetos com FreeRTOS&quot;,&quot;value&quot;:&quot;72-checklist-arquitetural-para-projetos-com-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Estrutura&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-estrutura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Comunica\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-comunica\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Prote\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-prote\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Estados e Modos&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-estados-e-modos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Arquitetura&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-arquitetura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;\u2714\ufe0f Inicializa\u00e7\u00e3o e Sa\u00fade&quot;,&quot;value&quot;:&quot;\u2714\ufe0f-inicializa\u00e7\u00e3o-e-sa\u00fade&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.3 Erros Cl\u00e1ssicos que Esses Padr\u00f5es Evitam&quot;,&quot;value&quot;:&quot;73-erros-cl\u00e1ssicos-que-esses-padr\u00f5es-evitam&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o&quot;,&quot;value&quot;:&quot;conclus\u00e3o&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução geral</a><li><a href="#eb-table-content-1">Padrões Fundamentais de Estruturação de Tarefas</a><ul class="eb-toc__list"><li><a href="#11-superloop-tasks-incremental-rtos-adoption">1.1 Superloop + Tasks (Incremental RTOS Adoption)</a><li><a href="#12-one-task-per-responsibility-uma-tarefa-por-responsabilidade">1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)</a><li><a href="#13-cyclic-executive-com-rtos">1.3 Cyclic Executive com RTOS</a><li><a href="#eb-table-content-5">1.4 Idle Task como Padrão Arquitetural</a></li></ul><li><a href="#eb-table-content-6">Padrões de Comunicação e Sincronização em RTOS</a><ul class="eb-toc__list"><li><a href="#21-event-queue-fila-de-eventos">2.1 Event Queue (Fila de Eventos)</a><li><a href="#eb-table-content-8">2.2 Mailbox (Fila de Mensagem Única)</a><li><a href="#23-publishsubscribe-pub-sub-com-freertos">2.3 Publish–Subscribe (Pub-Sub) com FreeRTOS</a><li><a href="#eb-table-content-10">2.4 Task Notification como Padrão de Sinalização Rápida</a><li><a href="#25-stream-buffer-e-message-buffer">2.5 Stream Buffer e Message Buffer</a><ul class="eb-toc__list"><li><a href="#stream-buffer">Stream Buffer</a><li><a href="#message-buffer">Message Buffer</a></li></ul></li></ul><li><a href="#eb-table-content-14">Padrões de Exclusão Mútua, Proteção de Recursos e Prevenção de Deadlock</a><ul class="eb-toc__list"><li><a href="#31-mutex-com-priority-inheritance">3.1 Mutex com Priority Inheritance</a><li><a href="#eb-table-content-16">3.2 Gatekeeper Task (Padrão Fundamental em FreeRTOS)</a><li><a href="#eb-table-content-17">3.3 Critical Section (Uso cirúrgico)</a><li><a href="#eb-table-content-18">3.4 Read–Modify–Write protegido (Anti-pattern clássico)</a><li><a href="#eb-table-content-19">3.5 Event Groups como Padrão de Coordenação</a><li><a href="#eb-table-content-20">3.6 Deadlock Avoidance (Padrões de Prevenção)</a></li></ul><li><a href="#eb-table-content-21">Padrões de Controle de Fluxo, Estados e Recuperação em RTOS</a><ul class="eb-toc__list"><li><a href="#eb-table-content-22">4.1 State Machine (Máquina de Estados Finita – FSM)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-23">Estrutura básica</a><li><a href="#eb-table-content-24">Execução da máquina de estados (task dedicada)</a></li></ul><li><a href="#42-hierarchical-state-machine-hsm">4.2 Hierarchical State Machine (HSM)</a><ul class="eb-toc__list"><li><a href="#exemplo-conceitual">Exemplo conceitual</a><li><a href="#eb-table-content-27">Implementação simplificada em C</a></li></ul><li><a href="#43-mode-manager-gerenciador-de-modos">4.3 Mode Manager (Gerenciador de Modos)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-29">Modos típicos</a><li><a href="#mode-manager">Mode Manager</a><li><a href="#uso-pelas-tarefas">Uso pelas tarefas</a></li></ul><li><a href="#eb-table-content-32">4.4 Recovery Pattern (Padrão de Recuperação)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-33">Exemplo de recuperação controlada</a></li></ul><li><a href="#eb-table-content-34">4.5 Watchdog como Padrão Arquitetural</a></li></ul><li><a href="#eb-table-content-35">Padrões de Arquitetura em Camadas, Drivers e Serviços em RTOS</a><ul class="eb-toc__list"><li><a href="#51-layered-architecture-arquitetura-em-camadas">5.1 Layered Architecture (Arquitetura em Camadas)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-37">Camadas típicas em FreeRTOS</a><li><a href="#eb-table-content-38">Exemplo de separação correta</a></li></ul><li><a href="#eb-table-content-39">5.2 Hardware Abstraction Layer (HAL) como Padrão</a><li><a href="#eb-table-content-40">5.3 Service Layer (Camada de Serviços)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-41">Exemplo: Serviço de UART com Gatekeeper</a></li></ul><li><a href="#54-active-object-pattern">5.4 Active Object Pattern</a><ul class="eb-toc__list"><li><a href="#estrutura-conceitual">Estrutura conceitual</a><li><a href="#exemplo-simplificado">Exemplo simplificado</a></li></ul><li><a href="#55-deferred-interrupt-processing">5.5 Deferred Interrupt Processing</a></li></ul><li><a href="#eb-table-content-46">Padrões de Inicialização, Startup Sequencial e Monitoramento de Saúde</a><ul class="eb-toc__list"><li><a href="#eb-table-content-47">6.1 Startup Task (Task de Inicialização)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-48">Estrutura típica</a></li></ul><li><a href="#eb-table-content-49">6.2 Init Sequencing (Sequenciamento de Inicialização)</a><ul class="eb-toc__list"><li><a href="#exemplo-com-event-groups">Exemplo com Event Groups</a></li></ul><li><a href="#63-dependency-ordering-pattern">6.3 Dependency Ordering Pattern</a><ul class="eb-toc__list"><li><a href="#exemplo-conceitual">Exemplo conceitual</a></li></ul><li><a href="#eb-table-content-53">6.4 Health Monitoring Pattern (Monitoramento de Saúde)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-54">Estrutura básica</a></li></ul><li><a href="#65-fail-safe-state-pattern">6.5 Fail-Safe State Pattern</a><li><a href="#66-warm-restart-vs-cold-restart">6.6 Warm Restart vs Cold Restart</a></li></ul><li><a href="#eb-table-content-57">Síntese Geral e Checklist Arquitetural de Padrões para FreeRTOS</a><ul class="eb-toc__list"><li><a href="#eb-table-content-58">7.1 Mapa Conceitual dos Padrões em RTOS</a><li><a href="#eb-table-content-59"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estrutura Básica</a><li><a href="#eb-table-content-60"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comunicação e Sincronização</a><li><a href="#eb-table-content-61"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Proteção de Recursos</a><li><a href="#eb-table-content-62"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Controle de Comportamento</a><li><a href="#eb-table-content-63"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Arquitetura Interna</a><li><a href="#eb-table-content-64"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Inicialização e Robustez</a><li><a href="#72-checklist-arquitetural-para-projetos-com-freertos">7.2 Checklist Arquitetural para Projetos com FreeRTOS</a><ul class="eb-toc__list"><li><a href="#eb-table-content-66"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estrutura</a><li><a href="#eb-table-content-67"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comunicação</a><li><a href="#eb-table-content-68"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Proteção</a><li><a href="#eb-table-content-69"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Estados e Modos</a><li><a href="#eb-table-content-70"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Arquitetura</a><li><a href="#eb-table-content-71"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Inicialização e Saúde</a></li></ul><li><a href="#eb-table-content-72">7.3 Erros Clássicos que Esses Padrões Evitam</a><li><a href="#eb-table-content-73">Conclusão</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading">Introdução geral</h2>



<p class="wp-block-paragraph">Em sistemas embarcados com RTOS, especialmente em aplicações industriais, automotivas e IoT crítico, o maior desafio não é apenas “fazer funcionar”, mas <strong>manter previsibilidade temporal, escalabilidade e manutenibilidade</strong>. É nesse ponto que os <strong>padrões de projeto aplicados a RTOS</strong> se tornam fundamentais.</p>



<p class="wp-block-paragraph">Diferente de aplicações desktop, padrões em RTOS precisam respeitar <strong>restrições de tempo real</strong>, <strong>uso determinístico de memória</strong>, <strong>prioridades</strong>, <strong>latência de interrupções</strong> e <strong>sincronização segura entre contexto de ISR e tarefas</strong>. Muitos padrões clássicos de software são adaptados ou reinterpretados nesse contexto.</p>



<p class="wp-block-paragraph">Neste artigo, começaremos pelos <strong>padrões estruturais básicos de tarefas</strong>, que formam a fundação de praticamente qualquer sistema com FreeRTOS.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Padrões Fundamentais de Estruturação de Tarefas</h2>



<h3 class="wp-block-heading">1.1 Superloop + Tasks (Incremental RTOS Adoption)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Projetos legados em superloop (<code>while(1)</code>) tornam-se difíceis de manter à medida que crescem. Migrar tudo de uma vez para RTOS é arriscado.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Manter o superloop como uma <strong>tarefa principal</strong>, introduzindo gradualmente novas tarefas RTOS.</p>



<p class="wp-block-paragraph"><strong>Quando usar:</strong></p>



<ul class="wp-block-list">
<li>Migração de firmware bare-metal para FreeRTOS</li>



<li>Sistemas simples que estão crescendo</li>



<li>Prototipação controlada</li>
</ul>



<p class="wp-block-paragraph"><strong>Estrutura típica:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void LegacySuperloopTask(void *pvParameters)
{
    for (;;)
    {
        ReadSensors();
        ProcessData();
        UpdateOutputs();

        vTaskDelay(pdMS_TO_TICKS(10));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">LegacySuperloopTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ReadSensors</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ProcessData</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">UpdateOutputs</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>xTaskCreate(
    LegacySuperloopTask,
    "Legacy",
    1024,
    NULL,
    tskIDLE_PRIORITY + 1,
    NULL
);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">LegacySuperloopTask</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Legacy</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">1024</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">NULL</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Baixo risco na migração</li>



<li>Preserva código validado</li>



<li>Facilita testes incrementais</li>
</ul>



<p class="wp-block-paragraph"><strong>Risco comum:</strong><br>Transformar essa tarefa em um “monstro” que ignora o espírito do RTOS. Este padrão <strong>deve ser transitório</strong>, não permanente.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.2 One Task Per Responsibility (Uma tarefa por responsabilidade)</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Tarefas que fazem “de tudo” dificultam análise temporal, debugging e escalonamento.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Cada tarefa possui <strong>uma única responsabilidade funcional bem definida</strong>.</p>



<p class="wp-block-paragraph"><strong>Exemplo típico em FreeRTOS:</strong></p>



<ul class="wp-block-list">
<li>Task de aquisição</li>



<li>Task de processamento</li>



<li>Task de comunicação</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void SensorTask(void *pvParameters)
{
    for (;;)
    {
        ReadADC();
        xTaskNotify(ProcessTaskHandle, 0, eNoAction);
        vTaskDelay(pdMS_TO_TICKS(5));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SensorTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ReadADC</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ProcessTaskHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void ProcessTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        FilterData();
        ComputeResults();
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ProcessTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ulTaskNotifyTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pdTRUE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">FilterData</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ComputeResults</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Facilita análise de prioridades</li>



<li>Reduz acoplamento</li>



<li>Favorece paralelismo real</li>
</ul>



<p class="wp-block-paragraph"><strong>Boas práticas:</strong></p>



<ul class="wp-block-list">
<li>Nomear tarefas claramente</li>



<li>Documentar WCET (Worst Case Execution Time)</li>



<li>Evitar bloqueios longos</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.3 Cyclic Executive com RTOS</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Algumas aplicações precisam de <strong>periodicidade rígida</strong>, mesmo usando RTOS.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Uma tarefa de alta prioridade atua como <strong>orquestrador temporal</strong>, liberando outras tarefas de forma cíclica.</p>



<p class="wp-block-paragraph"><strong>Estrutura conceitual:</strong></p>



<ul class="wp-block-list">
<li>Task cíclica principal</li>



<li>Subtarefas acionadas por notificações</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void CyclicTask(void *pvParameters)
{
    TickType_t xLastWakeTime = xTaskGetTickCount();

    for (;;)
    {
        xTaskNotify(TaskAHandle, 0, eNoAction);
        xTaskNotify(TaskBHandle, 0, eNoAction);

        vTaskDelayUntil(&amp;xLastWakeTime, pdMS_TO_TICKS(10));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">CyclicTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">TickType_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xLastWakeTime</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xTaskGetTickCount</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TaskAHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TaskBHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eNoAction</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelayUntil</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">xLastWakeTime</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Vantagens:</strong></p>



<ul class="wp-block-list">
<li>Controle temporal explícito</li>



<li>Previsibilidade elevada</li>



<li>Útil em controle e automação</li>
</ul>



<p class="wp-block-paragraph"><strong>Limitação:</strong><br>Menos flexível que arquiteturas puramente orientadas a eventos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.4 Idle Task como Padrão Arquitetural</h3>



<p class="wp-block-paragraph"><strong>Problema resolvido:</strong><br>Desperdício de CPU e energia quando o sistema está ocioso.</p>



<p class="wp-block-paragraph"><strong>Ideia do padrão:</strong><br>Usar a <strong>Idle Task</strong> como ponto central para:</p>



<ul class="wp-block-list">
<li>Economia de energia</li>



<li>Limpeza de recursos</li>



<li>Instrumentação</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void vApplicationIdleHook(void)
{
    EnterLowPowerMode();
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vApplicationIdleHook</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">EnterLowPowerMode</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Uso típico:</strong></p>



<ul class="wp-block-list">
<li><code>__WFI()</code> em Cortex-M</li>



<li>Estatísticas de CPU</li>



<li>Monitoramento de heap</li>
</ul>



<p class="wp-block-paragraph"><strong>Importante:</strong><br>Nunca bloquear, nunca usar delays e nunca acessar recursos não protegidos.</p><p>The post <a href="https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos/">Padrões de Projeto Aplicados a RTOS (FreeRTOS)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1198</post-id>	</item>
		<item>
		<title>FreeRTOS com lwIP: Arquitetura, Boas Práticas e Exemplos Reais de Sistemas Embarcados em Rede</title>
		<link>https://mcu.tec.br/rtos/freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 09:25:08 +0000</pubDate>
				<category><![CDATA[lwIP]]></category>
		<category><![CDATA[RTOS]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[LWIP]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1082</guid>

					<description><![CDATA[<p>Este artigo apresenta um guia completo e aprofundado sobre o uso do FreeRTOS em sistemas embarcados que utilizam a pilha de rede lwIP. O conteúdo aborda desde os fundamentos arquiteturais da integração entre RTOS e TCP/IP até padrões de projeto aplicados em firmware de produção. São exploradas as APIs do lwIP (RAW, Netconn e BSD Sockets), a função da TCP/IP thread, o uso correto de mailboxes, semáforos e filas do FreeRTOS, além de exemplos práticos em C envolvendo servidores TCP, arquitetura Gatekeeper, produtor/consumidor, framing de protocolos TCP, múltiplos clientes, timeouts, keepalive, backpressure e integração com Task Monitor e Watchdog. O artigo é voltado a desenvolvedores de sistemas embarcados que buscam robustez, previsibilidade temporal e boas práticas para aplicações conectadas em microcontroladores Cortex-M, ESP32 e plataformas similares, indo além de exemplos simplificados e focando em soluções aplicáveis ao ambiente industrial e de campo.</p>
<p>The post <a href="https://mcu.tec.br/rtos/freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede/">FreeRTOS com lwIP: Arquitetura, Boas Práticas e Exemplos Reais de Sistemas Embarcados em Rede</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h3 class="wp-block-heading"><strong>Introdução: FreeRTOS em sistemas com lwIP</strong></h3>



<p class="wp-block-paragraph">A combinação do <strong>FreeRTOS</strong> com a pilha de rede <strong>lwIP (Lightweight IP)</strong> é hoje uma das arquiteturas mais comuns em sistemas embarcados conectados, especialmente em microcontroladores Cortex-M (STM32, NXP, RP2040 com stack externa, ESP32 quando abstraído), onde há restrição severa de memória, tempo real e consumo energético. O FreeRTOS fornece o <strong>modelo concorrente determinístico</strong> (tarefas, prioridades, sincronização), enquanto o lwIP entrega uma <strong>implementação enxuta da pilha TCP/IP</strong>, compatível com IPv4, IPv6, TCP, UDP, ICMP, ARP, DHCP, DNS e HTTP, entre outros protocolos.</p>



<p class="wp-block-paragraph">O ponto crítico — e frequentemente negligenciado — é que o lwIP <strong>não é apenas uma biblioteca de rede</strong>, mas sim um <em>framework cooperativo</em> que precisa ser corretamente integrado ao <strong>modelo de execução do RTOS</strong>. Dependendo da configuração (RAW API, Netconn API ou BSD Sockets API), o lwIP pode operar de forma <strong>event-driven</strong>, <strong>thread-safe</strong> ou <strong>thread-aware</strong>, exigindo decisões arquiteturais bem fundamentadas. Uma escolha inadequada costuma resultar em <em>deadlocks</em>, <em>stack overflow</em>, perda de pacotes, latências imprevisíveis ou até <em>hard faults</em> difíceis de diagnosticar.</p>



<p class="wp-block-paragraph">Em sistemas com FreeRTOS, o lwIP normalmente é encapsulado em <strong>uma ou mais tarefas dedicadas</strong>, além de callbacks executados a partir de interrupções (ETH IRQ, DMA RX/TX) ou timers de software. Isso cria um ambiente híbrido onde <strong>código de interrupção, tarefas e a pilha TCP/IP</strong> precisam cooperar com rigor: uso correto de semáforos, mutexes, mailboxes (queues), buffers e prioridades. O entendimento dessa interação é essencial para construir aplicações robustas como <strong>servidores HTTP, MQTT brokers/clients, WebSockets, OTA, Modbus/TCP, Profinet sobre TCP/IP</strong>, entre outras.</p>



<p class="wp-block-paragraph">Nesta série de artigos, este material assume um <strong>cenário típico e realista</strong>:</p>



<ul class="wp-block-list">
<li>FreeRTOS rodando como sistema operacional principal</li>



<li>lwIP configurado com <strong>TCP/IP thread dedicada</strong></li>



<li>Interface Ethernet (MAC + PHY) ou driver de rede equivalente</li>



<li>Comunicação entre tarefas da aplicação e a pilha de rede</li>



<li>Ênfase em <strong>boas práticas, arquitetura correta e exemplos práticos em C</strong></li>
</ul>



<p class="wp-block-paragraph">Nas próximas seções, vamos avançar progressivamente, começando pela <strong>arquitetura interna do lwIP quando integrado ao FreeRTOS</strong>, passando pelas <strong>formas de integração (RAW, Netconn e Sockets)</strong>, até chegar a <strong>exemplos completos</strong> como servidor HTTP, cliente TCP e sincronização entre tarefas da aplicação e a pilha de rede.</p>



<h3 class="wp-block-heading"><strong>Arquitetura do lwIP em sistemas com FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Quando o lwIP é integrado a um sistema com FreeRTOS, ele deixa de ser apenas uma pilha TCP/IP “passiva” e passa a fazer parte ativa do <strong>modelo concorrente do sistema</strong>. O ponto central dessa arquitetura é a chamada <strong>TCP/IP thread</strong> (normalmente criada por <code>tcpip_init()</code>), que se torna o <strong>contexto exclusivo e soberano</strong> para quase todas as operações internas do lwIP. Isso significa que estruturas críticas como <em>PCB (Protocol Control Blocks)</em>, buffers <code>pbuf</code>, timers TCP e estados de conexão <strong>não são thread-safe por padrão</strong> e devem ser manipulados apenas dentro desse contexto controlado.</p>



<p class="wp-block-paragraph">Na prática, o lwIP organiza seu funcionamento em três grandes domínios de execução: <strong>interrupções de hardware</strong>, <strong>TCP/IP thread</strong> e <strong>tarefas da aplicação</strong>. As interrupções normalmente vêm do driver Ethernet (IRQ do MAC ou DMA RX/TX), cujo papel é mínimo: sinalizar que há pacotes recebidos ou buffers liberados, evitando qualquer processamento pesado. Essas interrupções acordam a TCP/IP thread por meio de <em>semaphores</em> ou <em>mailboxes</em>, garantindo que todo o processamento de protocolos ocorra fora do contexto de ISR, preservando determinismo e estabilidade do sistema.</p>



<p class="wp-block-paragraph">A TCP/IP thread funciona como um <strong>dispatcher de eventos de rede</strong>. Ela processa pacotes recebidos, executa timers periódicos (TCP retransmission, ARP aging, DHCP renewal), gerencia conexões e chama callbacks registrados pela aplicação. É aqui que reside uma armadilha comum: <strong>callbacks do lwIP não executam no contexto da task da aplicação</strong>, mas sim dentro da TCP/IP thread. Isso exige extremo cuidado ao acessar recursos compartilhados, como filas do FreeRTOS, buffers globais ou drivers de periféricos, sob pena de criar condições de corrida difíceis de rastrear.</p>



<p class="wp-block-paragraph">As tarefas da aplicação, por sua vez, <strong>nunca devem acessar diretamente estruturas internas do lwIP</strong>, exceto quando se utiliza APIs explicitamente thread-safe (como Netconn ou Sockets). Quando a arquitetura é bem desenhada, as tasks da aplicação se comunicam com a TCP/IP thread usando <strong>mensagens, filas ou chamadas assíncronas</strong>, mantendo uma separação clara entre lógica de negócio e infraestrutura de rede. Esse desacoplamento é um dos fatores-chave para escalabilidade e manutenibilidade do firmware.</p>



<p class="wp-block-paragraph">Do ponto de vista conceitual, pense no lwIP como um <strong>ator central</strong> que serializa todo o tráfego de rede, enquanto o FreeRTOS fornece o <strong>orquestrador de concorrência</strong> ao redor dele. Quando esse modelo é respeitado, o sistema se comporta de forma previsível mesmo sob carga elevada de rede. Quando é violado — por exemplo, chamando funções RAW do lwIP a partir de tasks arbitrárias — os sintomas surgem como bugs intermitentes, travamentos aleatórios ou degradação severa de desempenho.</p>



<p class="wp-block-paragraph">Na próxima seção, vamos entrar em um dos pontos mais críticos e confusos para quem trabalha com lwIP:<br><strong>as três APIs disponíveis (RAW API, Netconn API e BSD Sockets API)</strong>, explicando quando usar cada uma, suas vantagens, limitações e impactos diretos na arquitetura FreeRTOS.</p>



<h3 class="wp-block-heading"><strong>As APIs do lwIP no contexto do FreeRTOS: RAW, Netconn e Sockets</strong></h3>



<p class="wp-block-paragraph">Um dos pontos que mais geram confusão — e erros arquiteturais — no uso do lwIP com FreeRTOS é a existência de <strong>três APIs distintas</strong>, cada uma com <strong>modelos mentais, custos e implicações completamente diferentes</strong>. A escolha da API não é apenas uma questão de preferência sintática; ela define <strong>como as tasks interagem com a pilha TCP/IP</strong>, quais garantias de <em>thread-safety</em> existem e qual será o impacto em latência, uso de memória e complexidade do sistema.</p>



<p class="wp-block-paragraph">A <strong>RAW API</strong> é a forma mais direta e eficiente de usar o lwIP. Ela é totalmente <strong>event-driven</strong>, baseada em callbacks, e opera <strong>exclusivamente no contexto da TCP/IP thread</strong>. Não existe bloqueio, não existem semáforos implícitos, nem cópia adicional de buffers. Cada evento de rede — conexão estabelecida, dados recebidos, erro ou fechamento — dispara uma função de callback registrada previamente. Isso torna a RAW API ideal para sistemas com <strong>restrições severas de RAM e tempo real rígido</strong>, mas ao custo de maior complexidade cognitiva. Em sistemas FreeRTOS, a RAW API <strong>não deve ser chamada diretamente a partir de tasks da aplicação</strong>; qualquer interação precisa ser mediada por mensagens ou funções como <code>tcpip_callback()</code>.</p>



<p class="wp-block-paragraph">Já a <strong>Netconn API</strong> atua como uma camada intermediária entre a RAW API e o modelo tradicional de threads. Ela encapsula a lógica baseada em callbacks dentro de uma API <strong>bloqueante e thread-safe</strong>, usando <em>mailboxes</em> e <em>semaphores</em> internos. Para o desenvolvedor FreeRTOS, isso significa poder escrever código sequencial — <code>netconn_accept()</code>, <code>netconn_recv()</code>, <code>netconn_write()</code> — dentro de uma task, sem violar as regras internas do lwIP. O custo disso é um pequeno aumento de consumo de memória e latência, além de menos controle fino sobre eventos de baixo nível. Em projetos industriais, a Netconn API costuma ser um <strong>equilíbrio muito saudável entre robustez e simplicidade</strong>.</p>



<p class="wp-block-paragraph">A <strong>BSD Sockets API</strong>, por sua vez, é a mais familiar para quem vem do mundo Linux ou POSIX. Ela oferece funções como <code>socket()</code>, <code>bind()</code>, <code>listen()</code>, <code>accept()</code>, <code>recv()</code> e <code>send()</code>, com semântica muito próxima à de sistemas operacionais completos. Internamente, ela é construída sobre a Netconn API, herdando suas características e custos. Em FreeRTOS, a Sockets API facilita a portabilidade de código legado e acelera o desenvolvimento inicial, mas frequentemente induz a <strong>arquiteturas pobres</strong>, com tasks bloqueantes demais, pilha grande e baixa previsibilidade temporal se não for bem planejada.</p>



<p class="wp-block-paragraph">A decisão correta normalmente segue este raciocínio: se o sistema é <strong>altamente restrito e orientado a eventos</strong>, use RAW API; se precisa de <strong>clareza, robustez e integração limpa com FreeRTOS</strong>, use Netconn; se o foco é <strong>portabilidade e velocidade de desenvolvimento</strong>, a Sockets API pode ser aceitável — desde que o impacto em recursos seja cuidadosamente controlado. Em sistemas críticos, misturar APIs sem critério é uma receita certa para problemas difíceis de depurar.</p>



<p class="wp-block-paragraph">Na próxima seção, vamos aprofundar exatamente <strong>como o FreeRTOS e o lwIP se comunicam internamente</strong>, explorando <em>mailboxes</em>, <em>semaphores</em>, timers e a função <code>tcpip_init()</code>, com diagramas conceituais e exemplos práticos em C.</p>



<h3 class="wp-block-heading"><strong>Integração interna entre FreeRTOS e lwIP: mailboxes, semáforos e <code>tcpip_init()</code></strong></h3>



<p class="wp-block-paragraph">A espinha dorsal da integração entre FreeRTOS e lwIP é o <strong>mecanismo de mensagens assíncronas</strong> que garante que todo o processamento da pilha TCP/IP ocorra em um <strong>único contexto controlado</strong>. Esse contexto é criado pela chamada a <code>tcpip_init()</code>, responsável por inicializar o lwIP e criar a <strong>TCP/IP thread</strong>, além de suas estruturas de sincronização internas. Entender exatamente o que acontece aqui é essencial para evitar violações de <em>thread-safety</em> e erros sutis de concorrência.</p>



<p class="wp-block-paragraph">Quando <code>tcpip_init()</code> é chamada, o lwIP cria internamente uma task do FreeRTOS (normalmente chamada de <code>tcpip_thread</code>) e associa a ela uma <strong>mailbox principal</strong>. Essa mailbox funciona como uma fila de mensagens do RTOS, por onde chegam eventos como pacotes recebidos, timers expirados ou callbacks solicitados por outras tasks. O modelo é deliberadamente serial: a TCP/IP thread processa <strong>uma mensagem por vez</strong>, garantindo que as estruturas internas do lwIP nunca sejam acessadas concorrentemente.</p>



<p class="wp-block-paragraph">As <strong>interrupções de rede</strong> (por exemplo, RX DMA do Ethernet MAC) não processam protocolos diretamente. Em vez disso, elas apenas notificam o sistema — geralmente liberando um semáforo ou enviando um ponteiro de buffer para uma mailbox. O driver Ethernet, então, acorda a TCP/IP thread, que passa a processar os pacotes no contexto correto. Esse desenho é fundamental para manter <strong>latência previsível</strong> e evitar execução de código pesado em ISR, algo especialmente crítico em sistemas com FreeRTOS.</p>



<p class="wp-block-paragraph">Para permitir que tasks da aplicação interajam com o lwIP sem violar esse modelo, o lwIP fornece funções como <code>tcpip_callback()</code> e <code>tcpip_try_callback()</code>. Essas funções permitem que uma task qualquer solicite a execução de uma função <strong>dentro da TCP/IP thread</strong>, de forma assíncrona. Esse padrão é a base de arquiteturas seguras quando se utiliza a RAW API, pois impede acessos diretos às estruturas internas da pilha a partir de múltiplos contextos.</p>



<p class="wp-block-paragraph">A Netconn e a Sockets API se apoiam nesse mesmo mecanismo, mas encapsulam toda essa complexidade. Quando uma task chama <code>netconn_recv()</code>, por exemplo, o que acontece por baixo dos panos é um diálogo entre <strong>mailboxes internas</strong>, semáforos e a TCP/IP thread. A task da aplicação fica bloqueada de forma controlada, enquanto o lwIP continua operando normalmente. Isso explica por que essas APIs são thread-safe, mas também por que consomem mais RAM e stack.</p>



<p class="wp-block-paragraph">Um erro clássico em projetos é tentar “otimizar” esse fluxo acessando diretamente buffers, chamando funções RAW a partir de tasks comuns ou usando mutexes do FreeRTOS para proteger estruturas do lwIP. Essa abordagem <strong>não funciona</strong> e quebra premissas internas do stack. O modelo correto não é proteger o lwIP com mutexes, mas <strong>respeitar o confinamento de contexto imposto pela TCP/IP thread</strong>.</p>



<p class="wp-block-paragraph">Na próxima seção, vamos aplicar esses conceitos de forma concreta, construindo um <strong>exemplo prático de inicialização do lwIP com FreeRTOS</strong>, incluindo criação de tarefas, configuração do driver Ethernet e verificação do fluxo de dados.</p>



<h3 class="wp-block-heading"><strong>Exemplo prático: inicialização do lwIP em um sistema FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Nesta seção vamos sair do plano conceitual e entrar no <strong>código real</strong>, mostrando como um sistema típico FreeRTOS + lwIP é inicializado. O objetivo aqui não é apenas “fazer funcionar”, mas <strong>entender por que cada passo existe</strong>, qual o contexto de execução envolvido e quais são os erros clássicos que devem ser evitados.</p>



<p class="wp-block-paragraph">Assumiremos um cenário bastante comum em projetos industriais:</p>



<ul class="wp-block-list">
<li>FreeRTOS já inicializado</li>



<li>Interface Ethernet com driver próprio (MAC + PHY)</li>



<li>lwIP configurado para uso com <strong>TCP/IP thread dedicada</strong></li>



<li>Uso futuro de Netconn ou Sockets API</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>5.1 Ordem correta de inicialização</strong></h4>



<p class="wp-block-paragraph">A ordem de inicialização é <strong>crítica</strong>. Um erro frequente é criar tasks de aplicação que usam rede <strong>antes</strong> do lwIP estar totalmente operacional.</p>



<p class="wp-block-paragraph">A sequência correta, em alto nível, é:</p>



<ol class="wp-block-list">
<li>Inicializar hardware básico (clock, GPIO, PHY, MAC)</li>



<li>Inicializar o lwIP (<code>tcpip_init</code>)</li>



<li>Configurar interface de rede (<code>netif</code>)</li>



<li>Subir a interface (<code>netif_set_up</code>)</li>



<li>Só então criar tasks da aplicação que usam rede</li>



<li>Iniciar o scheduler do FreeRTOS</li>
</ol>



<p class="wp-block-paragraph">Essa ordem garante que nenhuma task tente acessar a pilha TCP/IP fora do contexto correto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>5.2 Inicializando o lwIP (<code>tcpip_init</code>)</strong></h4>



<p class="wp-block-paragraph">O primeiro ponto de integração direta entre FreeRTOS e lwIP é a chamada a <code>tcpip_init()</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "lwip/tcpip.h"

static void lwip_init_done(void *arg)
{
    /* Callback chamado quando a TCP/IP thread está pronta */
    (void)arg;
}

void lwip_stack_init(void)
{
    tcpip_init(lwip_init_done, NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/tcpip.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lwip_init_done</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Callback chamado quando a TCP/IP thread está pronta */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lwip_stack_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">tcpip_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">lwip_init_done</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">O que acontece aqui, de fato:</p>



<ul class="wp-block-list">
<li>O lwIP cria internamente a <strong>TCP/IP thread</strong> como uma task do FreeRTOS</li>



<li>São criadas mailboxes internas para troca de mensagens</li>



<li>Timers internos do TCP/IP são registrados</li>



<li>O callback <code>lwip_init_done()</code> é executado <strong>no contexto da TCP/IP thread</strong>, não na task chamadora</li>
</ul>



<p class="wp-block-paragraph">Esse detalhe é importante: qualquer código executado nesse callback já está em um <strong>contexto seguro para chamadas RAW</strong>, caso necessário.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>5.3 Configuração da interface de rede (<code>netif</code>)</strong></h4>



<p class="wp-block-paragraph">Após a inicialização do lwIP, precisamos registrar a interface de rede:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/dhcp.h"

static struct netif netif_eth;

void netif_config(void)
{
    ip4_addr_t ipaddr;
    ip4_addr_t netmask;
    ip4_addr_t gw;

    IP4_ADDR(&amp;ipaddr, 0, 0, 0, 0);   /* DHCP */
    IP4_ADDR(&amp;netmask, 0, 0, 0, 0);
    IP4_ADDR(&amp;gw, 0, 0, 0, 0);

    netif_add(&amp;netif_eth,
              &amp;ipaddr,
              &amp;netmask,
              &amp;gw,
              NULL,
              ethernetif_init,
              tcpip_input);

    netif_set_default(&amp;netif_eth);
    netif_set_up(&amp;netif_eth);

    dhcp_start(&amp;netif_eth);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/netif.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/ip_addr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/dhcp.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">netif</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">netif_eth</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">netif_config</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ip4_addr_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ipaddr</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ip4_addr_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">netmask</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ip4_addr_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gw</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">IP4_ADDR</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">ipaddr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">/* DHCP */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">IP4_ADDR</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netmask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">IP4_ADDR</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">gw</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">netif_add</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netif_eth</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">ipaddr</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netmask</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">gw</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #D8DEE9">ethernetif_init</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #D8DEE9">tcpip_input</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">netif_set_default</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netif_eth</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">netif_set_up</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netif_eth</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">dhcp_start</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">netif_eth</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Aqui aparecem alguns pontos arquiteturais importantes:</p>



<ul class="wp-block-list">
<li><code>ethernetif_init</code> é o <strong>driver de baixo nível</strong>, responsável por integrar MAC/PHY ao lwIP</li>



<li><code>tcpip_input</code> garante que pacotes recebidos sejam entregues <strong>à TCP/IP thread</strong>, e não processados no contexto errado</li>



<li>O uso de DHCP é opcional, mas comum em sistemas conectados</li>
</ul>



<p class="wp-block-paragraph">Essa função normalmente é chamada <strong>após</strong> <code>tcpip_init()</code> e <strong>antes</strong> da criação das tasks de aplicação.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>5.4 Criação das tasks da aplicação</strong></h4>



<p class="wp-block-paragraph">Somente depois que a pilha está pronta é que criamos tasks que usam rede:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void network_task(void *argument)
{
    /* A partir daqui, é seguro usar Netconn ou Sockets API */
    for (;;)
    {
        /* Lógica de rede */
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_start(void)
{
    xTaskCreate(network_task,
                "NetTask",
                1024,
                NULL,
                tskIDLE_PRIORITY + 2,
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">network_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">argument</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* A partir daqui, é seguro usar Netconn ou Sockets API */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Lógica de rede */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">app_start</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">network_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">NetTask</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">1024</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Note que:</p>



<ul class="wp-block-list">
<li>A task <strong>não interage diretamente com estruturas RAW</strong></li>



<li>O tamanho da stack já precisa considerar buffers de rede</li>



<li>A prioridade deve ser pensada em conjunto com a TCP/IP thread</li>
</ul>



<p class="wp-block-paragraph">Um erro comum é dar prioridade muito baixa para a TCP/IP thread e alta para tasks de aplicação, o que resulta em <strong>timeouts, perda de pacotes e conexões instáveis</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>5.5 Erros clássicos nesta fase</strong></h4>



<p class="wp-block-paragraph">Alguns problemas recorrentes que surgem exatamente nesse ponto:</p>



<ul class="wp-block-list">
<li>Criar sockets antes do <code>netif_set_up</code></li>



<li>Chamar funções RAW a partir de tasks comuns</li>



<li>Executar processamento pesado no driver Ethernet (ISR)</li>



<li>Stack insuficiente para tasks de rede</li>



<li>Prioridade inadequada da TCP/IP thread</li>
</ul>



<p class="wp-block-paragraph">Todos esses erros levam a sintomas difíceis de diagnosticar, como travamentos aleatórios ou falhas intermitentes de comunicação.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na próxima seção, vamos construir um <strong>exemplo completo de servidor TCP/HTTP</strong>, mostrando como uma task FreeRTOS usa a <strong>Netconn ou Sockets API</strong> corretamente, com explicação detalhada de cada chamada.</p>



<h3 class="wp-block-heading"><strong>Exemplo completo: servidor TCP usando Sockets API em uma task FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Aqui vamos montar um servidor TCP simples (estilo “echo server” + base para HTTP) rodando em uma <strong>task do FreeRTOS</strong> usando a <strong>BSD Sockets API do lwIP</strong>. A ideia é te dar um esqueleto real que funciona em 80% dos firmwares conectados: uma task aceita conexões, recebe dados, responde e fecha. Em seguida, vou apontar onde normalmente você evolui para HTTP, MQTT, Modbus/TCP etc.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>6.1 Requisitos e premissas</strong></h4>



<p class="wp-block-paragraph">Para usar Sockets no lwIP você normalmente precisa ter (no <code>lwipopts.h</code>):</p>



<ul class="wp-block-list">
<li><code>LWIP_SOCKET=1</code></li>



<li><code>LWIP_NETCONN=1</code> (sockets geralmente dependem dela)</li>



<li><code>LWIP_TCP=1</code></li>



<li><code>LWIP_DNS=1</code> (se quiser resolver nomes)</li>



<li><code>LWIP_DHCP=1</code> (se usar DHCP)</li>
</ul>



<p class="wp-block-paragraph">E lembrar do modelo: <strong>a task de sockets é sua</strong>, mas o lwIP continua processando rede na <strong>TCP/IP thread</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>6.2 Código do servidor TCP (com comentários didáticos)</strong></h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "FreeRTOS.h"
#include "task.h"

#include "lwip/sockets.h"
#include "lwip/inet.h"
#include &lt;string.h>
#include &lt;stdio.h>

/* Ajuste conforme sua aplicação */
#define SERVER_PORT     5000
#define RX_BUF_SIZE     1024
#define LISTEN_BACKLOG  4

static void tcp_server_task(void *arg)
{
    (void)arg;

    int listen_fd = -1;
    int client_fd = -1;

    struct sockaddr_in addr;
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    /* Buffer local: cuidado com stack! */
    char rx_buf&#91;RX_BUF_SIZE&#93;;

    /* 1) Criar socket TCP */
    listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listen_fd &lt; 0) {
        /* Em sistemas embarcados: logue e reinicie a task ou sinalize falha */
        vTaskDelete(NULL);
    }

    /* 2) Preencher estrutura de endereço */
    memset(&amp;addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERVER_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY); /* escuta em todas interfaces */

    /* 3) Bind: amarra o socket à porta */
    if (bind(listen_fd, (struct sockaddr *)&amp;addr, sizeof(addr)) &lt; 0) {
        closesocket(listen_fd);
        vTaskDelete(NULL);
    }

    /* 4) Listen: coloca em modo servidor */
    if (listen(listen_fd, LISTEN_BACKLOG) &lt; 0) {
        closesocket(listen_fd);
        vTaskDelete(NULL);
    }

    for (;;)
    {
        /* 5) Accept: bloqueia esperando cliente */
        client_fd = accept(listen_fd, (struct sockaddr *)&amp;client_addr, &amp;client_len);
        if (client_fd &lt; 0) {
            /* Se accept falhar, normalmente você continua tentando */
            vTaskDelay(pdMS_TO_TICKS(100));
            continue;
        }

        /* 6) Loop de recepção */
        for (;;)
        {
            int n = recv(client_fd, rx_buf, sizeof(rx_buf) - 1, 0);
            if (n &lt;= 0) {
                /* n == 0 -> cliente fechou; n &lt; 0 -> erro */
                break;
            }

            rx_buf&#91;n&#93; = '\0';

            /* 7) Aqui entra a lógica da aplicação.
                  Para um echo server: devolve os bytes recebidos. */
            send(client_fd, rx_buf, n, 0);

            /* Exemplo: se quiser encerrar ao receber "quit" */
            if (strncmp(rx_buf, "quit", 4) == 0) {
                break;
            }
        }

        /* 8) Fecha conexão do cliente */
        closesocket(client_fd);
        client_fd = -1;
    }
}

/* Função de arranque */
void start_tcp_server(void)
{
    /* Stack precisa ser dimensionada: sockets + buffer local */
    xTaskCreate(tcp_server_task,
                "TCPServer",
                2048,                  /* ajuste real conforme seu MCU/heap */
                NULL,
                tskIDLE_PRIORITY + 2,  /* prioridade média */
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/sockets.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/inet.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdio</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Ajuste conforme sua aplicação */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF">     </span><span style="color: #B48EAD">5000</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RX_BUF_SIZE</span><span style="color: #D8DEE9FF">     </span><span style="color: #B48EAD">1024</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LISTEN_BACKLOG</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">4</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">tcp_server_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr_in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">addr</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr_in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_addr</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">socklen_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_addr</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Buffer local: cuidado com stack! */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rx_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">RX_BUF_SIZE</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* 1) Criar socket TCP */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AF_INET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOCK_STREAM</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Em sistemas embarcados: logue e reinicie a task ou sinalize falha */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* 2) Preencher estrutura de endereço */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_family</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AF_INET</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_port</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htons</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">s_addr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htonl</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">INADDR_ANY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* escuta em todas interfaces */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* 3) Bind: amarra o socket à porta */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">bind</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* 4) Listen: coloca em modo servidor */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">listen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LISTEN_BACKLOG</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* 5) Accept: bloqueia esperando cliente */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">accept</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">client_addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">client_len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Se accept falhar, normalmente você continua tentando */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* 6) Loop de recepção */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">recv</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rx_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rx_buf</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #616E88">/* n == 0 -&gt; cliente fechou; n &lt; 0 -&gt; erro */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">rx_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\0</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* 7) Aqui entra a lógica da aplicação.</span></span>
<span class="line"><span style="color: #616E88">                  Para um echo server: devolve os bytes recebidos. */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">send</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rx_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Exemplo: se quiser encerrar ao receber &quot;quit&quot; */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">strncmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rx_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">quit</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* 8) Fecha conexão do cliente */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Função de arranque */</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">start_tcp_server</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Stack precisa ser dimensionada: sockets + buffer local */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tcp_server_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TCPServer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">                  </span><span style="color: #616E88">/* ajuste real conforme seu MCU/heap */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* prioridade média */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>6.3 Pontos críticos (onde a maioria erra)</strong></h4>



<p class="wp-block-paragraph">A primeira armadilha é stack. Repare que <code>rx_buf[1024]</code> está na stack da task. Em Cortex-M, 2 KB de stack pode ficar apertado se você começar a montar respostas HTTP grandes, fazer parsing pesado ou usar <code>printf</code>. Uma prática robusta é mover buffers grandes para heap/estático e deixar stack para variáveis pequenas.</p>



<p class="wp-block-paragraph">A segunda armadilha é bloqueio infinito. <code>accept()</code> e <code>recv()</code> bloqueiam. Isso pode ser OK em um servidor dedicado, mas se você precisa de shutdown limpo, watchdog cooperativo ou multiplexar atividades, você vai querer <strong>timeouts</strong> via <code>setsockopt()</code> com <code>SO_RCVTIMEO</code> e <code>SO_SNDTIMEO</code>, ou usar <code>select()</code> para multiplexar.</p>



<p class="wp-block-paragraph">A terceira armadilha é “fazer tudo nessa task”. Em firmware sério, o servidor de sockets vira um <strong>front-end</strong> que entrega payloads para outras tasks via <strong>queues</strong> (produtor/consumidor), mantendo o servidor leve e previsível. Caso contrário, você mistura rede + lógica de negócio + acesso a periféricos no mesmo contexto e cria latência ruim e travamentos em cascata.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>6.4 Melhorando com timeouts (essencial para robustez)</strong></h4>



<p class="wp-block-paragraph">Um exemplo direto para evitar travar em <code>recv()</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &amp;tv, sizeof(tv));
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">timeval</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tv</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_sec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_usec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_RCVTIMEO</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tv</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Com isso, <code>recv()</code> retorna erro após 5 s sem dados, e você pode encerrar a conexão ou apenas continuar.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na próxima seção, vamos fazer exatamente o que transforma esse exemplo em arquitetura “de produção”:</p>



<ul class="wp-block-list">
<li><strong>Task de sockets como Gatekeeper</strong></li>



<li>Entrega de dados para uma <strong>fila FreeRTOS</strong></li>



<li>Um ou mais <strong>consumidores</strong> processando requisições</li>



<li>Resposta retornando ao cliente de forma segura</li>
</ul>



<h3 class="wp-block-heading"><strong>Arquitetura de produção: servidor de sockets como Gatekeeper + filas FreeRTOS (produtor/consumidor)</strong></h3>



<p class="wp-block-paragraph">Quando você coloca lwIP + FreeRTOS em um produto real, a pergunta não é “como abrir um socket”, mas sim: <strong>como garantir previsibilidade, isolamento de falhas e escalabilidade</strong> quando há múltiplas conexões, parsing de protocolo, acesso a periféricos e regras de negócio rodando ao mesmo tempo. O padrão mais sólido aqui é tratar a task de rede como um <strong>Gatekeeper</strong> (porteiro): ela faz o mínimo necessário (I/O de rede e framing básico), empacota mensagens e entrega para a aplicação via <strong>Queue</strong>. As tasks de aplicação, por sua vez, consomem essas mensagens e devolvem respostas por um caminho igualmente controlado.</p>



<p class="wp-block-paragraph">A razão técnica é simples: a pilha de rede precisa de tempo de CPU para manter conexões (ACKs, retransmissões, janelas TCP), e isso pode ser prejudicado se você faz parsing pesado, acesso a flash, escrita em SD, controle de motores ou logs complexos dentro da mesma task que está segurando o socket. Além disso, erros na lógica de negócio não podem derrubar a infraestrutura de rede. Com Gatekeeper + filas, você desacopla os domínios: rede continua estável, aplicação pode reiniciar tasks de processamento, e o sistema ganha uma arquitetura “defensiva”.</p>



<p class="wp-block-paragraph">A seguir, vamos montar um exemplo funcional e didático. Ele não é “o menor possível”: ele é “o mais correto possível” para firmware.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>7.1 Estruturas de mensagem e filas</strong></h4>



<p class="wp-block-paragraph">Vamos definir duas filas:</p>



<ul class="wp-block-list">
<li><code>rxQueue</code>: mensagens recebidas da rede para a aplicação</li>



<li><code>txQueue</code>: respostas da aplicação para serem transmitidas pela task de rede</li>
</ul>



<p class="wp-block-paragraph">Cada mensagem precisa carregar, no mínimo:</p>



<ul class="wp-block-list">
<li><strong>identificador da conexão</strong> (socket do cliente ou um handle abstrato)</li>



<li><strong>payload</strong> (bytes recebidos)</li>



<li><strong>tamanho</strong></li>



<li><strong>metadados</strong> (opcional: IP/porta, timestamp etc.)</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "FreeRTOS.h"
#include "queue.h"
#include &lt;stdint.h>

#define MAX_PAYLOAD 512

typedef struct
{
    int client_fd;                 /* Identifica a conexão */
    uint16_t len;
    uint8_t payload&#91;MAX_PAYLOAD&#93;;  /* Mensagem "copiada" para trânsito seguro */
} NetMessage_t;

static QueueHandle_t rxQueue;
static QueueHandle_t txQueue;

void net_queues_init(void)
{
    rxQueue = xQueueCreate(8, sizeof(NetMessage_t));
    txQueue = xQueueCreate(8, sizeof(NetMessage_t));
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">queue.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_PAYLOAD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">512</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">                 </span><span style="color: #616E88">/* Identifica a conexão */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">MAX_PAYLOAD</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Mensagem &quot;copiada&quot; para trânsito seguro */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">txQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">net_queues_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">rxQueue</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xQueueCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">8</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">txQueue</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xQueueCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">8</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Observação crítica:</strong> aqui estamos usando cópia de payload. Em sistemas mais exigentes, você pode migrar para <em>zero-copy</em> com <code>pbuf</code> (RAW API) ou pool de buffers. Mas começar com cópia é geralmente a forma mais estável de construir algo robusto e debugar rápido.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>7.2 Task Gatekeeper: recebe do socket e entrega na <code>rxQueue</code></strong></h4>



<p class="wp-block-paragraph">A task de rede agora vira uma “central de I/O”: aceita conexões, recebe dados e empacota mensagens para a fila.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "lwip/sockets.h"
#include "lwip/inet.h"
#include &lt;string.h>

#define SERVER_PORT 5000

static void socket_gatekeeper_task(void *arg)
{
    (void)arg;

    int listen_fd;
    struct sockaddr_in addr;

    listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listen_fd &lt; 0) vTaskDelete(NULL);

    memset(&amp;addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERVER_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(listen_fd, (struct sockaddr *)&amp;addr, sizeof(addr)) &lt; 0) {
        closesocket(listen_fd);
        vTaskDelete(NULL);
    }

    if (listen(listen_fd, 4) &lt; 0) {
        closesocket(listen_fd);
        vTaskDelete(NULL);
    }

    for (;;)
    {
        int client_fd = accept(listen_fd, NULL, NULL);
        if (client_fd &lt; 0) {
            vTaskDelay(pdMS_TO_TICKS(50));
            continue;
        }

        /* Exemplo simples: atende 1 cliente por vez.
           Em produção você pode criar uma task por cliente OU usar select(). */
        for (;;)
        {
            NetMessage_t msg;
            int n = recv(client_fd, msg.payload, MAX_PAYLOAD, 0);
            if (n &lt;= 0) break;

            msg.client_fd = client_fd;
            msg.len = (uint16_t)n;

            /* Entrega para aplicação: se a fila estiver cheia, você precisa decidir política:
               - descartar
               - bloquear por tempo limitado
               - desconectar cliente
            */
            if (xQueueSend(rxQueue, &amp;msg, pdMS_TO_TICKS(20)) != pdPASS) {
                /* Política simples: descarta e segue */
            }

            /* Antes de receber mais, veja se há resposta pronta para este cliente */
            NetMessage_t out;
            if (xQueueReceive(txQueue, &amp;out, 0) == pdPASS) {
                if (out.client_fd == client_fd &amp;&amp; out.len > 0) {
                    send(client_fd, out.payload, out.len, 0);
                } else {
                    /* Se veio resposta de outro cliente, em produção você
                       rotearia corretamente (mapa de conexões, etc.) */
                }
            }
        }

        closesocket(client_fd);
    }
}

void start_socket_gatekeeper(void)
{
    xTaskCreate(socket_gatekeeper_task,
                "NetGate",
                2048,
                NULL,
                tskIDLE_PRIORITY + 3, /* Um pouco acima da aplicação */
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">queue.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/sockets.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/inet.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5000</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket_gatekeeper_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr_in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">addr</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AF_INET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOCK_STREAM</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_family</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AF_INET</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_port</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htons</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">s_addr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htonl</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">INADDR_ANY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">bind</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">listen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">accept</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">50</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Exemplo simples: atende 1 cliente por vez.</span></span>
<span class="line"><span style="color: #616E88">           Em produção você pode criar uma task por cliente OU usar select(). */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">recv</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_PAYLOAD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">n</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Entrega para aplicação: se a fila estiver cheia, você precisa decidir política:</span></span>
<span class="line"><span style="color: #616E88">               - descartar</span></span>
<span class="line"><span style="color: #616E88">               - bloquear por tempo limitado</span></span>
<span class="line"><span style="color: #616E88">               - desconectar cliente</span></span>
<span class="line"><span style="color: #616E88">            */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rxQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">20</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #616E88">/* Política simples: descarta e segue */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Antes de receber mais, veja se há resposta pronta para este cliente */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">send</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #616E88">/* Se veio resposta de outro cliente, em produção você</span></span>
<span class="line"><span style="color: #616E88">                       rotearia corretamente (mapa de conexões, etc.) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">start_socket_gatekeeper</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">socket_gatekeeper_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">NetGate</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* Um pouco acima da aplicação */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Por que esse desenho é bom?</strong> Porque o Gatekeeper mantém I/O simples e previsível: ele não interpreta protocolo nem acessa hardware. Ele apenas “empurra bytes”.</p>



<p class="wp-block-paragraph"><strong>Crítica (importante):</strong> este exemplo atende um cliente por vez. Para múltiplos clientes, as duas opções típicas são:</p>



<ol class="wp-block-list">
<li><strong>uma task por conexão</strong> (mais simples, mas consome RAM/stack)</li>



<li><strong><code>select()</code></strong> com um loop único multiplexando sockets (mais eficiente, mais complexo)</li>
</ol>



<p class="wp-block-paragraph">Na próxima seção eu te mostro os dois modelos, mas antes precisamos fechar o ciclo com o consumidor.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>7.3 Task consumidora: processa mensagem e devolve resposta</strong></h4>



<p class="wp-block-paragraph">Agora a lógica de aplicação recebe mensagens da <code>rxQueue</code>, interpreta e devolve uma resposta pela <code>txQueue</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include &lt;string.h>

static void app_worker_task(void *arg)
{
    (void)arg;

    for (;;)
    {
        NetMessage_t in;
        if (xQueueReceive(rxQueue, &amp;in, portMAX_DELAY) == pdPASS)
        {
            NetMessage_t out;
            memset(&amp;out, 0, sizeof(out));

            out.client_fd = in.client_fd;

            /* Exemplo de "protocolo": comandos ASCII */
            if (in.len >= 4 &amp;&amp; memcmp(in.payload, "ping", 4) == 0) {
                const char *resp = "pong\n";
                out.len = (uint16_t)strlen(resp);
                memcpy(out.payload, resp, out.len);
            } else {
                const char *resp = "unknown\n";
                out.len = (uint16_t)strlen(resp);
                memcpy(out.payload, resp, out.len);
            }

            /* Envia resposta para o Gatekeeper transmitir */
            (void)xQueueSend(txQueue, &amp;out, pdMS_TO_TICKS(50));
        }
    }
}

void start_app_worker(void)
{
    xTaskCreate(app_worker_task,
                "AppWorker",
                2048,
                NULL,
                tskIDLE_PRIORITY + 2,
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">queue.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">app_worker_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rxQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;in</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Exemplo de &quot;protocolo&quot;: comandos ASCII */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">memcmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ping</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">pong</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">resp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">unknown</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">resp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Envia resposta para o Gatekeeper transmitir */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">50</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">start_app_worker</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">app_worker_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">AppWorker</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Aqui você ganhou algo decisivo: se o parsing for pesado, você pode criar <strong>vários workers consumidores</strong> (ou uma pool) sem mexer na task de rede. E se um worker travar, você pode reiniciá-lo sem derrubar a rede (principalmente se tiver Task Monitor/Watchdog como você já vem tratando na série).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>7.4 Ajustes essenciais para “produção”</strong></h4>



<p class="wp-block-paragraph">O exemplo acima é a forma didática mais direta, mas em firmware real você geralmente aplica melhorias:</p>



<ul class="wp-block-list">
<li><strong>Roteamento de respostas por conexão:</strong> em vez de uma <code>txQueue</code> única, você cria uma fila por cliente (ou um mapa de conexões).</li>



<li><strong>Política de backpressure:</strong> se <code>rxQueue</code> enche, você reduz leitura do socket, aplica <code>recv</code> com timeout, ou desconecta cliente.</li>



<li><strong>Framing:</strong> TCP é stream, não pacote. Seu “comando” pode vir partido em múltiplos <code>recv()</code>. Então você implementa <em>framing</em> (por delimitador <code>\n</code>, por tamanho fixo, ou por header com length).</li>



<li><strong>Stack e heap:</strong> payload copiado custa RAM; quando necessário, migra para pool de buffers.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na próxima seção, vamos atacar exatamente o que separa “demo” de “produto”:<br><strong>TCP é stream — então precisamos de framing e parser robusto</strong>, além de <strong>timeouts</strong> e <strong>manuseio de múltiplos clientes</strong>.</p>



<h3 class="wp-block-heading"><strong> TCP é stream: framing robusto + múltiplos clientes (task por conexão vs <code>select()</code>)</strong></h3>



<p class="wp-block-paragraph">Se tem um erro conceitual que derruba sistemas FreeRTOS + lwIP “do nada”, é tratar <code>recv()</code> como se cada chamada retornasse uma mensagem completa. <strong>TCP não entrega mensagens — entrega um fluxo (stream)</strong>. Isso significa que um comando <code>ping\n</code> pode chegar como <code>p</code>, depois <code>ing\n</code>, ou pode chegar junto com outro comando colado, ou pode vir com bytes extras. Se você não implementar <strong>framing</strong>, sua aplicação vai funcionar em bancada e falhar sob carga, ruído de rede, latência variável ou retransmissões.</p>



<p class="wp-block-paragraph">A solução arquitetural é definir um protocolo com framing claro. Os dois modelos mais comuns em firmware são: (1) <strong>delimitador</strong> (por exemplo <code>\n</code>) e (2) <strong>length-prefix</strong> (header com tamanho). Vou te mostrar os dois, e em seguida mostro como isso muda quando você tem múltiplos clientes: ou você cria <strong>uma task por conexão</strong> (simples, mais RAM) ou usa <strong><code>select()</code></strong> (eficiente, mais complexo).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>8.1 Framing por delimitador (<code>\n</code>)</strong></h4>



<p class="wp-block-paragraph">Esse é o mais simples: você acumula bytes num buffer até achar <code>\n</code>. Cada linha vira um comando. É ótimo para console TCP, debug remoto, protocolos ASCII e comandos humanos. O cuidado é evitar overflow: se o cliente mandar uma linha enorme sem <code>\n</code>, você precisa cortar, descartar ou desconectar.</p>



<p class="wp-block-paragraph">Exemplo de acumulador por conexão:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include &lt;string.h>
#include &lt;stdint.h>

#define LINE_BUF_SZ 256

typedef struct
{
    uint8_t buf&#91;LINE_BUF_SZ&#93;;
    uint16_t used;
} LineFramer_t;

/**
 * @brief Alimenta o framer com bytes recebidos e extrai 0..N linhas completas.
 *        Retorna 1 quando extraiu uma linha, 0 quando ainda não tem linha.
 */
static int framer_try_get_line(LineFramer_t *f, const uint8_t *data, uint16_t len,
                               uint8_t *out_line, uint16_t *out_len)
{
    /* Copia com proteção */
    uint16_t space = (LINE_BUF_SZ - 1) - f->used;
    if (len > space) {
        /* Política simples: reset (em produção: desconectar cliente) */
        f->used = 0;
        return 0;
    }

    memcpy(&amp;f->buf&#91;f->used&#93;, data, len);
    f->used += len;
    f->buf&#91;f->used&#93; = 0;

    /* Procura delimitador */
    uint8_t *nl = (uint8_t*)memchr(f->buf, '\n', f->used);
    if (!nl) return 0;

    uint16_t line_len = (uint16_t)(nl - f->buf) + 1; /* inclui '\n' */
    memcpy(out_line, f->buf, line_len);
    *out_len = line_len;

    /* Remove a linha do buffer (shift) */
    uint16_t remaining = f->used - line_len;
    memmove(f->buf, &amp;f->buf&#91;line_len&#93;, remaining);
    f->used = remaining;

    return 1;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">256</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">used</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Alimenta o framer com bytes recebidos e extrai 0..N linhas completas.</span></span>
<span class="line"><span style="color: #616E88"> *        Retorna 1 quando extraiu uma linha, 0 quando ainda não tem linha.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">framer_try_get_line</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                               </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Copia com proteção */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">space</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">space</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Política simples: reset (em produção: desconectar cliente) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Procura delimitador */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">memchr</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* inclui &#39;\n&#39; */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out_line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Remove a linha do buffer (shift) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memmove</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Uso típico no loop do socket: você chama <code>recv()</code>, joga os bytes no framer e enquanto ele conseguir extrair linhas você envia para a fila (<code>rxQueue</code>).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>8.2 Framing por header com tamanho (length-prefix)</strong></h4>



<p class="wp-block-paragraph">Esse é o padrão de protocolos binários robustos. Você define, por exemplo:</p>



<ul class="wp-block-list">
<li>2 bytes: <code>len</code> (big-endian)</li>



<li><code>len</code> bytes: payload</li>
</ul>



<p class="wp-block-paragraph">Vantagem: não depende de delimitador e funciona bem com binário. Desvantagem: você precisa validar tamanho, lidar com endianess e limites.</p>



<p class="wp-block-paragraph">Estrutura de parsing por estados:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include &lt;stdint.h>
#include &lt;string.h>

#define MAX_FRAME 512

typedef enum { ST_LEN1, ST_LEN2, ST_PAYLOAD } ParseState_t;

typedef struct
{
    ParseState_t st;
    uint16_t expected;
    uint16_t got;
    uint8_t payload&#91;MAX_FRAME&#93;;
} LenFramer_t;

static void lenframer_init(LenFramer_t *f)
{
    f->st = ST_LEN1;
    f->expected = 0;
    f->got = 0;
}

/**
 * @brief Consome bytes e extrai frames completos. Retorna 1 quando extrai um frame.
 */
static int lenframer_feed(LenFramer_t *f, const uint8_t *data, uint16_t len,
                          uint8_t *out_payload, uint16_t *out_len)
{
    for (uint16_t i = 0; i &lt; len; i++)
    {
        uint8_t b = data&#91;i&#93;;

        switch (f->st)
        {
            case ST_LEN1:
                f->expected = ((uint16_t)b) &lt;&lt; 8;
                f->st = ST_LEN2;
                break;

            case ST_LEN2:
                f->expected |= b;
                if (f->expected == 0 || f->expected > MAX_FRAME) {
                    /* Frame inválido: reset (em produção: desconectar) */
                    lenframer_init(f);
                    break;
                }
                f->got = 0;
                f->st = ST_PAYLOAD;
                break;

            case ST_PAYLOAD:
                f->payload&#91;f->got++&#93; = b;
                if (f->got >= f->expected) {
                    memcpy(out_payload, f->payload, f->expected);
                    *out_len = f->expected;
                    lenframer_init(f);
                    return 1; /* extraiu 1 frame */
                }
                break;
        }
    }
    return 0;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">512</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParseState_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParseState_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">st</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">expected</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">got</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Consome bytes e extrai frames completos. Retorna 1 quando extrai um frame.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lenframer_feed</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">switch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> ((</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">b</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #616E88">/* Frame inválido: reset (em produção: desconectar) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out_payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* extraiu 1 frame */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse modelo é extremamente estável em ambiente real porque mantém o protocolo bem definido.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>8.3 Múltiplos clientes: duas arquiteturas</strong></h4>



<p class="wp-block-paragraph">Agora vem o ponto de engenharia de firmware: <strong>como atender N conexões</strong> sem destruir RAM e sem perder previsibilidade.</p>



<p class="wp-block-paragraph"><strong>Opção A — Uma task por conexão (modelo simples)</strong></p>



<ul class="wp-block-list">
<li>Ao aceitar um cliente, você cria uma task dedicada para ele.</li>



<li>Cada task tem seu framer + buffer + loop <code>recv()</code>.</li>



<li>Fácil de entender e depurar.</li>



<li>Custo: cada task consome stack e TCB; em MCU pequeno isso vira limite rápido.</li>
</ul>



<p class="wp-block-paragraph">Padrão típico:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static void client_task(void *arg)
{
    int client_fd = (int)(intptr_t)arg;
    LineFramer_t fr;
    fr.used = 0;

    for (;;)
    {
        uint8_t tmp&#91;128&#93;;
        int n = recv(client_fd, tmp, sizeof(tmp), 0);
        if (n &lt;= 0) break;

        uint8_t line&#91;LINE_BUF_SZ&#93;;
        uint16_t line_len;

        while (framer_try_get_line(&amp;fr, tmp, (uint16_t)n, line, &amp;line_len)) {
            /* aqui você empacota e manda para rxQueue */
        }
    }

    closesocket(client_fd);
    vTaskDelete(NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">client_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">intptr_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fr</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">fr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">128</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">recv</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tmp</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">framer_try_get_line</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">fr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">n</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">)) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* aqui você empacota e manda para rxQueue */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Opção B — <code>select()</code> (modelo eficiente)</strong></p>



<ul class="wp-block-list">
<li>Uma única task monitora vários sockets ao mesmo tempo.</li>



<li>Melhor uso de RAM (uma task só), bom para dezenas de conexões.</li>



<li>Custo: mais complexo; exige tabela de conexões e estados por cliente.</li>
</ul>



<p class="wp-block-paragraph">Se seu firmware precisa escalar, <code>select()</code> costuma ser o caminho. Se precisa ser simples e você terá poucos clientes, task por conexão é perfeito.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>8.4 Um detalhe que muita gente ignora: prioridade e latência</strong></h4>



<p class="wp-block-paragraph">Não adianta ter framing perfeito se a task que atende sockets fica “no fim da fila” e perde janela TCP. Em geral, uma prática saudável é:</p>



<ul class="wp-block-list">
<li>TCP/IP thread: prioridade média-alta (depende do port e do vendor)</li>



<li>Gatekeeper de sockets: prioridade logo abaixo da TCP/IP thread</li>



<li>Workers de aplicação: prioridade média</li>



<li>Logs/telemetria: prioridade baixa</li>
</ul>



<p class="wp-block-paragraph">Isso evita um cenário em que o processamento de aplicação “engole” a CPU e a rede degrada.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na próxima seção, vamos fechar a arquitetura com os componentes que tornam isso resiliente em produto:</p>



<ul class="wp-block-list">
<li><strong>timeouts completos</strong> (recv/send/connect/accept)</li>



<li><strong>keepalive TCP</strong></li>



<li><strong>watchdog e task monitor aplicados ao domínio de rede</strong></li>



<li><strong>política de backpressure</strong> quando filas enchem</li>



<li>e um exemplo “quase HTTP” com parser mínimo</li>
</ul>



<h3 class="wp-block-heading"><strong>Robustez em rede: timeouts, keepalive, backpressure e integração com Task Monitor/Watchdog</strong></h3>



<p class="wp-block-paragraph">Até aqui você já tem uma arquitetura correta. Agora entramos no que diferencia <strong>firmware de laboratório</strong> de <strong>firmware de campo</strong>: resiliência. Em sistemas FreeRTOS + lwIP, a maior parte das falhas em produção não vem de bugs óbvios, mas de <strong>bloqueios silenciosos</strong>, <strong>clientes mal-comportados</strong>, <strong>perda intermitente de link</strong>, <strong>filas saturadas</strong> e <strong>tarefas que parecem vivas, mas não fazem progresso</strong>. Esta seção trata exatamente desses pontos — com decisões práticas de engenharia.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.1 Timeouts em sockets: nunca confie em bloqueios infinitos</strong></h4>



<p class="wp-block-paragraph">Chamadas como <code>accept()</code>, <code>recv()</code> e <code>send()</code> <strong>bloqueiam por padrão</strong>. Em firmware, isso é perigoso: se um cliente trava no meio de uma transmissão, sua task pode ficar presa indefinidamente, impedindo shutdown limpo, watchdog cooperativo e diagnóstico.</p>



<p class="wp-block-paragraph">A regra é simples: <strong>todo socket deve ter timeout</strong>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static void socket_set_timeouts(int fd, int sec)
{
    struct timeval tv;
    tv.tv_sec = sec;
    tv.tv_usec = 0;

    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &amp;tv, sizeof(tv));
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &amp;tv, sizeof(tv));
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket_set_timeouts</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sec</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">timeval</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tv</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_sec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sec</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_usec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_RCVTIMEO</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tv</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_SNDTIMEO</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tv</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Use isso logo após <code>accept()</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int client_fd = accept(listen_fd, NULL, NULL);
if (client_fd >= 0) {
    socket_set_timeouts(client_fd, 5); /* 5s é um bom ponto inicial */
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">accept</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">socket_set_timeouts</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* 5s é um bom ponto inicial */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Com isso:</p>



<ul class="wp-block-list">
<li><code>recv()</code> retorna <code>&lt; 0</code> após timeout</li>



<li>você pode <strong>encerrar a conexão</strong>, <strong>reavaliar estado</strong> ou <strong>alimentar watchdog</strong></li>



<li>evita tarefas “zumbis”</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.2 TCP Keepalive: detectando clientes mortos</strong></h4>



<p class="wp-block-paragraph">Em redes reais, cliente pode cair sem fechar socket (queda de Wi-Fi, cabo puxado, crash). O TCP keepalive permite detectar isso.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int enable = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &amp;enable, sizeof(enable));

int idle = 10;    /* segundos ociosos antes do probe */
int interval = 5; /* intervalo entre probes */
int count = 3;    /* probes antes de declarar morto */

setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &amp;idle, sizeof(idle));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &amp;interval, sizeof(interval));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &amp;count, sizeof(count));
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enable</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_KEEPALIVE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">enable</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">enable</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">idle</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* segundos ociosos antes do probe */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">interval</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* intervalo entre probes */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">count</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* probes antes de declarar morto */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPIDLE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">idle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">idle</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPINTVL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">interval</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">interval</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPCNT</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">count</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">count</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Nem todos os ports do lwIP suportam todas essas opções, mas quando disponíveis, <strong>reduzem drasticamente conexões zumbis</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.3 Backpressure: o que fazer quando as filas enchem</strong></h4>



<p class="wp-block-paragraph">Esse ponto é crítico e raramente tratado em exemplos. Se sua <code>rxQueue</code> enche, <strong>o sistema está dizendo que não consegue processar dados na mesma taxa em que recebe</strong>. Ignorar isso leva a latência crescente e colapso.</p>



<p class="wp-block-paragraph">Existem quatro políticas clássicas:</p>



<ol class="wp-block-list">
<li><strong>Descartar mensagens novas</strong><br>Simples, mas pode quebrar protocolo.</li>



<li><strong>Bloquear o Gatekeeper por tempo limitado</strong><code>if (xQueueSend(rxQueue, &amp;msg, pdMS_TO_TICKS(50)) != pdPASS) { /* timeout: decide política */ }</code></li>



<li><strong>Parar de ler do socket temporariamente</strong><br>Com timeout em <code>recv()</code>, você simplesmente não chama <code>recv</code> por um ciclo.</li>



<li><strong>Desconectar cliente agressivo</strong> (muito comum em produto)<br>Se um cliente gera backpressure constante, ele é o problema.</li>
</ol>



<p class="wp-block-paragraph">Em firmware sério, a política 4 costuma ser a mais segura.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.4 Integração com Task Monitor: detectar “tarefas vivas porém travadas”</strong></h4>



<p class="wp-block-paragraph">Uma task bloqueada em <code>recv()</code> <strong>não parece travada</strong> para o scheduler — ela está em estado <em>Blocked</em>. Por isso, Task Monitor precisa ir além de “task rodando ou não”: precisa verificar <strong>progresso lógico</strong>.</p>



<p class="wp-block-paragraph">Modelo simples: <em>heartbeat por domínio</em>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>volatile uint32_t net_heartbeat = 0;

void socket_gatekeeper_task(void *arg)
{
    for (;;)
    {
        net_heartbeat++;
        /* accept / recv / processamento */
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">volatile</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket_gatekeeper_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* accept / recv / processamento */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">O Task Monitor verifica:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static uint32_t last_net_hb = 0;

void task_monitor(void)
{
    if (net_heartbeat == last_net_hb) {
        /* rede não progrediu */
        /* ação: reiniciar task, reiniciar interface, logar */
    }
    last_net_hb = net_heartbeat;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">task_monitor</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* rede não progrediu */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* ação: reiniciar task, reiniciar interface, logar */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Isso detecta:</p>



<ul class="wp-block-list">
<li>deadlocks</li>



<li>starvation</li>



<li>loops bloqueados por erro lógico</li>
</ul>



<p class="wp-block-paragraph">Muito mais eficaz que apenas checar se a task existe.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.5 Watchdog cooperativo aplicado à rede</strong></h4>



<p class="wp-block-paragraph">Nunca alimente o watchdog <strong>dentro da task de sockets diretamente</strong>. Isso mascara falhas. O correto é:</p>



<ul class="wp-block-list">
<li>task de rede atualiza estado/heartbeat</li>



<li><strong>task de supervisão</strong> decide se o sistema está saudável</li>



<li>só ela alimenta o watchdog</li>
</ul>



<p class="wp-block-paragraph">Exemplo conceitual:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void supervisor_task(void *arg)
{
    for (;;)
    {
        if (net_ok &amp;&amp; app_ok &amp;&amp; sensors_ok) {
            feed_watchdog();
        }
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">supervisor_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">net_ok</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app_ok</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sensors_ok</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">feed_watchdog</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">500</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Assim, falhas de rede <strong>resetam o sistema</strong>, em vez de ficarem ocultas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>9.6 Mini-HTTP: aplicação prática dos conceitos</strong></h4>



<p class="wp-block-paragraph">Para fechar, um exemplo conceitual de servidor estilo HTTP minimalista:</p>



<ul class="wp-block-list">
<li>framing por <code>\r\n\r\n</code></li>



<li>timeout curto</li>



<li>parsing mínimo</li>



<li>resposta fixa</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>if (strstr(request, "GET /status")) {
    const char *resp =
        "HTTP/1.1 200 OK\r\n"
        "Content-Type: text/plain\r\n"
        "Connection: close\r\n"
        "\r\n"
        "OK\n";
    send(fd, resp, strlen(resp), 0);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">strstr</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">request</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">GET /status</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">HTTP/1.1 200 OK</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Content-Type: text/plain</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Connection: close</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">OK</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">send</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">resp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resp</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Em firmware, <strong>HTTP raramente precisa ser completo</strong>. Muitas vezes é só um protocolo humano para debug, status e configuração inicial. Quanto mais simples, mais confiável.</p><p>The post <a href="https://mcu.tec.br/rtos/freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede/">FreeRTOS com lwIP: Arquitetura, Boas Práticas e Exemplos Reais de Sistemas Embarcados em Rede</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1082</post-id>	</item>
		<item>
		<title>FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</title>
		<link>https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freertos-uso-correto-de-queue-com-multiplos-consumidores</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 27 Feb 2026 19:03:41 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[comunicação entre tarefas]]></category>
		<category><![CDATA[escalonador FreeRTOS]]></category>
		<category><![CDATA[event groups]]></category>
		<category><![CDATA[filas em RTOS]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[múltiplos consumidores]]></category>
		<category><![CDATA[queue FreeRTOS]]></category>
		<category><![CDATA[RTOS em microcontroladores]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[task notifications]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1059</guid>

					<description><![CDATA[<p>Aprenda como usar corretamente Queue com múltiplos consumidores no FreeRTOS. Entenda o impacto do escalonador, riscos de starvation, perda de eventos e quando usar alternativas como Event Groups e Task Notifications para criar firmwares robustos e previsíveis.</p>
<p>The post <a href="https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/">FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-gumxp wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-gumxp "><div class="eb-toc-container eb-toc-gumxp  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;text&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;text&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;text&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;text&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-filas-no-freertos-e-o-cen\u00e1rio-de-m\u00faltiplos-consumidores&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;value&quot;:&quot;modelos-cl\u00e1ssicos-de-m\u00faltiplos-consumidores-e-o-impacto-no-escalonador&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;value&quot;:&quot;cuidados-essenciais-e-armadilhas-comuns-ao-usar-queue-com-v\u00e1rios-consumidores&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;value&quot;:&quot;alternativas-arquiteturais-quando-m\u00faltiplos-consumidores-precisam-do-mesmo-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-diretrizes-de-projeto-e-fechamento&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução: filas no FreeRTOS e o cenário de múltiplos consumidores</a><li><a href="#eb-table-content-1">Modelos clássicos de múltiplos consumidores e o impacto no escalonador</a><li><a href="#eb-table-content-2">Cuidados essenciais e armadilhas comuns ao usar Queue com vários consumidores</a><li><a href="#eb-table-content-3">Alternativas arquiteturais quando múltiplos consumidores precisam do mesmo evento</a><li><a href="#eb-table-content-4">Boas práticas, diretrizes de projeto e fechamento</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading">Introdução: filas no FreeRTOS e o cenário de múltiplos consumidores</h3>



<p class="wp-block-paragraph">No FreeRTOS, <strong>Queue</strong> é um dos mecanismos centrais de comunicação e sincronização entre tarefas. Diferente de simples buffers, uma fila carrega não apenas dados, mas também <strong>semântica de sincronização</strong>, permitindo que tarefas produtoras e consumidoras operem de forma desacoplada no tempo. Em sistemas reais — especialmente em firmware para sensores, comunicação, aquisição de dados e pipelines de processamento — é muito comum termos <strong>um produtor e vários consumidores</strong>, todos interessados nos dados que chegam pela mesma fila.</p>



<p class="wp-block-paragraph">O primeiro ponto importante, e frequentemente negligenciado, é que <strong>uma Queue do FreeRTOS não é um mecanismo de broadcast</strong>. Ela segue estritamente o modelo <em>FIFO</em> (First-In, First-Out) com <strong>remoção destrutiva do item</strong>. Isso significa que, quando múltiplas tarefas consumidoras bloqueiam na mesma fila, <strong>apenas uma delas receberá cada item enviado</strong>, e essa escolha é feita pelo escalonador com base em prioridade e estado das tarefas. Esse detalhe muda completamente a forma como o sistema deve ser arquitetado.</p>



<p class="wp-block-paragraph">Esse comportamento é ideal quando os consumidores representam <strong>workers concorrentes</strong>, ou seja, tarefas equivalentes que disputam trabalho. Um exemplo clássico é um sistema em que uma interrupção de ADC empilha amostras em uma fila, e várias tarefas de processamento estatístico competem para consumir esses dados. Nesse caso, a fila atua como um <em>work queue</em>, balanceando carga automaticamente entre os consumidores.</p>



<p class="wp-block-paragraph">Por outro lado, quando o objetivo é que <strong>todos os consumidores vejam todos os eventos</strong>, a Queue isoladamente é a escolha errada. Muitos bugs em sistemas embarcados com FreeRTOS surgem exatamente desse equívoco conceitual: o desenvolvedor assume que várias tarefas “escutando” a mesma fila receberão as mesmas mensagens, o que simplesmente não acontece. Esse erro se manifesta como perda intermitente de eventos, estados inconsistentes e falhas difíceis de reproduzir.</p>



<p class="wp-block-paragraph">Para ilustrar o cenário correto de múltiplos consumidores concorrentes, considere o exemplo abaixo, onde várias tarefas processam mensagens vindas de um único produtor:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
    uint32_t id;
    uint16_t value;
} message_t;

QueueHandle_t xQueue;

void vProducerTask(void *pvParameters)
{
    message_t msg;
    uint32_t counter = 0;

    for (;;)
    {
        msg.id = counter++;
        msg.value = counter * 10;

        xQueueSend(xQueue, &amp;msg, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void vConsumerTask(void *pvParameters)
{
    message_t msg;

    for (;;)
    {
        if (xQueueReceive(xQueue, &amp;msg, portMAX_DELAY) == pdPASS)
        {
            /* Cada mensagem será processada por APENAS um consumidor */
            process_message(&amp;msg);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">id</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">message_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vProducerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">message_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">id</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vConsumerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">message_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Cada mensagem será processada por APENAS um consumidor */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">process_message</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Nesse modelo, várias instâncias de <code>vConsumerTask</code> podem ser criadas, e cada mensagem enviada pelo produtor será entregue a apenas uma delas. O FreeRTOS garante exclusão mútua implícita no acesso à fila, evitando a necessidade de mutex para esse fluxo específico.</p>



<p class="wp-block-paragraph">Nesta artigo, vamos aprofundar <strong>quando esse modelo é ideal</strong>, <strong>quais implicações surgem em termos de escalonamento, prioridade e starvation</strong>, <strong>como evitar armadilhas comuns</strong>, e <strong>quais alternativas arquiteturais devem ser usadas quando o requisito é difusão (fan-out) e não competição</strong>.</p><p>The post <a href="https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/">FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1059</post-id>	</item>
		<item>
		<title>Arquitetura Orientada a Eventos no FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arquitetura-orientada-a-eventos-no-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 17:44:13 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura orientada a eventos]]></category>
		<category><![CDATA[event groups]]></category>
		<category><![CDATA[filas FreeRTOS]]></category>
		<category><![CDATA[firmware reativo]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[message buffers]]></category>
		<category><![CDATA[programação em tempo real]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[sistemas determinísticos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[software timers]]></category>
		<category><![CDATA[stream buffers]]></category>
		<category><![CDATA[task notifications]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1057</guid>

					<description><![CDATA[<p>Meta descrição (≥ 600 caracteres):<br />
Este artigo apresenta uma abordagem técnica e didática sobre arquitetura orientada a eventos no FreeRTOS, explicando como projetar firmwares reativos, determinísticos e eficientes para sistemas embarcados. São analisados em profundidade os principais mecanismos do FreeRTOS, como Task Notifications, Event Groups, Queues, Stream Buffers, Message Buffers e Software Timers, sempre sob a ótica de engenharia de software embarcado. O texto demonstra como combinar corretamente esses mecanismos para evitar polling, reduzir consumo de CPU e energia, minimizar latência e melhorar a manutenção do código. Com exemplos práticos em C, análise de padrões arquiteturais e discussão dos erros mais comuns, o artigo serve como guia completo para desenvolvedores que desejam construir sistemas escaláveis, previsíveis e alinhados às melhores práticas de tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/">Arquitetura Orientada a Eventos no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-zyou1 wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-zyou1 "><div class="eb-toc-container eb-toc-zyou1  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;O que vem a seguir&quot;,&quot;text&quot;:&quot;O que vem a seguir&quot;,&quot;link&quot;:&quot;o-que-vem-a-seguir&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;text&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;link&quot;:&quot;modelo-conceitual-da-arquitetura-orientada-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;text&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;text&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;link&quot;:&quot;exemplo-conceitual-simplificado&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;text&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;text&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;link&quot;:&quot;task-notifications-como-mecanismo-central-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;text&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;link&quot;:&quot;modelo-mental-correto-para-task-notifications&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;link&quot;:&quot;exemplo-2-contador-de-eventos-acumulados&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;text&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;link&quot;:&quot;exemplo-3-task-notification-como-bitmap-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;text&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;link&quot;:&quot;vantagens-arquiteturais-das-task-notifications&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;text&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;text&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;link&quot;:&quot;modelo-de-uso-correto-para-event-groups&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Uso em ISRs&quot;,&quot;text&quot;:&quot;Uso em ISRs&quot;,&quot;link&quot;:&quot;uso-em-isrs&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;text&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;link&quot;:&quot;armadilhas-comuns-no-uso-de-event-groups&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;text&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;link&quot;:&quot;queues-e-message-passing-em-arquiteturas-orientadas-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;text&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;link&quot;:&quot;modelo-conceitual-de-filas-orientadas-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;link&quot;:&quot;exemplo-2-fila-como-buffer-de-desacoplamento&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;text&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;link&quot;:&quot;uso-combinado-queue-task-notification&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;text&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;text&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;link&quot;:&quot;stream-buffers-e-message-buffers-para-fluxos-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;text&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;link&quot;:&quot;exemplo-1-stream-buffer-com-uart&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;text&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;text&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;link&quot;:&quot;exemplo-2-message-buffer-para-comandos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;text&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilhas comuns&quot;,&quot;text&quot;:&quot;Armadilhas comuns&quot;,&quot;link&quot;:&quot;armadilhas-comuns&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;text&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;link&quot;:&quot;software-timers-como-geradores-de-eventos-temporais&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;text&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;link&quot;:&quot;modelo-conceitual-correto-para-software-timers&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;link&quot;:&quot;exemplo-1-timer-gerando-evento-simples&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;text&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;link&quot;:&quot;exemplo-3-timer-como-agendador-leve-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;text&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;link&quot;:&quot;prioridade-da-timer-service-task&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;text&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;text&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;text&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;text&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;text&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;link&quot;:&quot;eb-table-content-42&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;text&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;link&quot;:&quot;eb-table-content-43&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;text&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-44&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;text&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;link&quot;:&quot;eb-table-content-45&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;text&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;link&quot;:&quot;eb-table-content-46&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;text&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-47&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;text&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;link&quot;:&quot;eb-table-content-48&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;text&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;link&quot;:&quot;erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;text&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;link&quot;:&quot;eb-table-content-50&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;text&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;link&quot;:&quot;erro-5-tasks-que-nunca-bloqueiam&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;text&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;link&quot;:&quot;erro-6-misturar-estado-e-evento&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;text&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;link&quot;:&quot;erro-7-overengineering-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;text&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;link&quot;:&quot;eb-table-content-54&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;text&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;link&quot;:&quot;eb-table-content-55&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;text&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;link&quot;:&quot;eb-table-content-56&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;text&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;link&quot;:&quot;arquitetura-orientada-a-eventos-como-base-para-escalabilidade&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-e-motiva\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que vem a seguir&quot;,&quot;value&quot;:&quot;o-que-vem-a-seguir&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;value&quot;:&quot;modelo-conceitual-da-arquitetura-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;value&quot;:&quot;fluxo-t\u00edpico-de-eventos-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;value&quot;:&quot;exemplo-conceitual-simplificado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;value&quot;:&quot;implica\u00e7\u00f5es-arquiteturais-importantes&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;value&quot;:&quot;task-notifications-como-mecanismo-central-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;value&quot;:&quot;modelo-mental-correto-para-task-notifications&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;value&quot;:&quot;exemplo-1-evento-simples-sinaliza\u00e7\u00e3o-pura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;value&quot;:&quot;exemplo-2-contador-de-eventos-acumulados&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;value&quot;:&quot;exemplo-3-task-notification-como-bitmap-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;value&quot;:&quot;vantagens-arquiteturais-das-task-notifications&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;value&quot;:&quot;event-groups-coordena\u00e7\u00e3o-de-m\u00faltiplos-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;value&quot;:&quot;modelo-de-uso-correto-para-event-groups&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;value&quot;:&quot;exemplo-1-aguardando-m\u00faltiplos-eventos-simult\u00e2neos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;value&quot;:&quot;exemplo-2-sinaliza\u00e7\u00e3o-parcial-e-limpeza-autom\u00e1tica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso em ISRs&quot;,&quot;value&quot;:&quot;uso-em-isrs&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;value&quot;:&quot;armadilhas-comuns-no-uso-de-event-groups&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;value&quot;:&quot;queues-e-message-passing-em-arquiteturas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;value&quot;:&quot;modelo-conceitual-de-filas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;value&quot;:&quot;exemplo-1-evento-com-payload-isr-\u2192-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;value&quot;:&quot;exemplo-2-fila-como-buffer-de-desacoplamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;value&quot;:&quot;uso-combinado-queue-task-notification&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;value&quot;:&quot;implica\u00e7\u00f5es-de-projeto-e-dimensionamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;value&quot;:&quot;stream-buffers-e-message-buffers-para-fluxos-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;value&quot;:&quot;stream-buffers-eventos-como-fluxo-cont\u00ednuo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;value&quot;:&quot;exemplo-1-stream-buffer-com-uart&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;value&quot;:&quot;thresholds-e-controle-de-lat\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;value&quot;:&quot;message-buffers-eventos-com-mensagens-vari\u00e1veis&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;value&quot;:&quot;exemplo-2-message-buffer-para-comandos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;value&quot;:&quot;compara\u00e7\u00e3o-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilhas comuns&quot;,&quot;value&quot;:&quot;armadilhas-comuns&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;value&quot;:&quot;software-timers-como-geradores-de-eventos-temporais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;value&quot;:&quot;modelo-conceitual-correto-para-software-timers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;value&quot;:&quot;exemplo-1-timer-gerando-evento-simples&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;value&quot;:&quot;exemplo-2-timer-peri\u00f3dico-como-evento-de-sistema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;value&quot;:&quot;exemplo-3-timer-como-agendador-leve-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;value&quot;:&quot;prioridade-da-timer-service-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;value&quot;:&quot;integra\u00e7\u00e3o-com-arquiteturas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;value&quot;:&quot;composi\u00e7\u00e3o-arquitetural-de-eventos-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;value&quot;:&quot;padr\u00e3o-1-isr-m\u00ednima-evento-direcionado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;value&quot;:&quot;padr\u00e3o-2-evento-acorda-fila-transporta&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;value&quot;:&quot;padr\u00e3o-3-event-group-como-estado-global-n\u00e3o-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;value&quot;:&quot;padr\u00e3o-4-timer-\u2192-evento-\u2192-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;value&quot;:&quot;padr\u00e3o-5-m\u00e1quina-de-estados-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;value&quot;:&quot;princ\u00edpios-arquiteturais-que-emergem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;value&quot;:&quot;erros-arquiteturais-comuns-e-como-evit\u00e1-los&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;value&quot;:&quot;erro-1-polling-disfar\u00e7ado-de-arquitetura-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;value&quot;:&quot;erro-2-l\u00f3gica-pesada-dentro-de-isrs&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;value&quot;:&quot;erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;value&quot;:&quot;erro-4-fila-gen\u00e9rica-para-tudo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;value&quot;:&quot;erro-5-tasks-que-nunca-bloqueiam&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;value&quot;:&quot;erro-6-misturar-estado-e-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;value&quot;:&quot;erro-7-overengineering-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;value&quot;:&quot;checklist-arquitetural-pr\u00e1tico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;value&quot;:&quot;conclus\u00e3o-t\u00e9cnica-boas-pr\u00e1ticas-e-impacto-no-projeto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-consolidadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;value&quot;:&quot;arquitetura-orientada-a-eventos-como-base-para-escalabilidade&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução e Motivação</a><li><a href="#o-que-vem-a-seguir">O que vem a seguir</a><li><a href="#modelo-conceitual-da-arquitetura-orientada-a-eventos">Modelo Conceitual da Arquitetura Orientada a Eventos</a><li><a href="#eb-table-content-3">Fluxo típico de eventos no FreeRTOS</a><li><a href="#exemplo-conceitual-simplificado">Exemplo conceitual simplificado</a><li><a href="#eb-table-content-5">Implicações arquiteturais importantes</a><li><a href="#task-notifications-como-mecanismo-central-de-eventos">Task Notifications como Mecanismo Central de Eventos</a><li><a href="#modelo-mental-correto-para-task-notifications">Modelo mental correto para Task Notifications</a><li><a href="#eb-table-content-8">Exemplo 1 — Evento simples (sinalização pura)</a><li><a href="#exemplo-2-contador-de-eventos-acumulados">Exemplo 2 — Contador de eventos acumulados</a><li><a href="#exemplo-3-task-notification-como-bitmap-de-eventos">Exemplo 3 — Task Notification como bitmap de eventos</a><li><a href="#vantagens-arquiteturais-das-task-notifications">Vantagens arquiteturais das Task Notifications</a><li><a href="#eb-table-content-12">Event Groups: Coordenação de Múltiplos Eventos</a><li><a href="#modelo-de-uso-correto-para-event-groups">Modelo de uso correto para Event Groups</a><li><a href="#eb-table-content-14">Exemplo 1 — Aguardando múltiplos eventos simultâneos</a><li><a href="#eb-table-content-15">Exemplo 2 — Sinalização parcial e limpeza automática</a><li><a href="#uso-em-isrs">Uso em ISRs</a><li><a href="#armadilhas-comuns-no-uso-de-event-groups">Armadilhas comuns no uso de Event Groups</a><li><a href="#queues-e-message-passing-em-arquiteturas-orientadas-a-eventos">Queues e Message Passing em Arquiteturas Orientadas a Eventos</a><li><a href="#modelo-conceitual-de-filas-orientadas-a-eventos">Modelo conceitual de filas orientadas a eventos</a><li><a href="#eb-table-content-20">Exemplo 1 — Evento com payload (ISR → Task)</a><li><a href="#exemplo-2-fila-como-buffer-de-desacoplamento">Exemplo 2 — Fila como buffer de desacoplamento</a><li><a href="#uso-combinado-queue-task-notification">Uso combinado: Queue + Task Notification</a><li><a href="#eb-table-content-23">Implicações de projeto e dimensionamento</a><li><a href="#stream-buffers-e-message-buffers-para-fluxos-de-eventos">Stream Buffers e Message Buffers para Fluxos de Eventos</a><li><a href="#eb-table-content-25">Stream Buffers — Eventos como fluxo contínuo</a><li><a href="#exemplo-1-stream-buffer-com-uart">Exemplo 1 — Stream Buffer com UART</a><li><a href="#eb-table-content-27">Thresholds e controle de latência</a><li><a href="#eb-table-content-28">Message Buffers — Eventos com mensagens variáveis</a><li><a href="#exemplo-2-message-buffer-para-comandos">Exemplo 2 — Message Buffer para comandos</a><li><a href="#eb-table-content-30">Comparação arquitetural</a><li><a href="#armadilhas-comuns">Armadilhas comuns</a><li><a href="#software-timers-como-geradores-de-eventos-temporais">Software Timers como Geradores de Eventos Temporais</a><li><a href="#modelo-conceitual-correto-para-software-timers">Modelo conceitual correto para Software Timers</a><li><a href="#exemplo-1-timer-gerando-evento-simples">Exemplo 1 — Timer gerando evento simples</a><li><a href="#eb-table-content-35">Exemplo 2 — Timer periódico como evento de sistema</a><li><a href="#exemplo-3-timer-como-agendador-leve-de-eventos">Exemplo 3 — Timer como agendador leve de eventos</a><li><a href="#prioridade-da-timer-service-task">Prioridade da Timer Service Task</a><li><a href="#eb-table-content-38">Integração com arquiteturas orientadas a eventos</a><li><a href="#eb-table-content-39">Composição Arquitetural de Eventos no FreeRTOS</a><li><a href="#eb-table-content-40">Padrão 1 — ISR mínima + Evento Direcionado</a><li><a href="#eb-table-content-41">Padrão 2 — Evento acorda, fila transporta</a><li><a href="#eb-table-content-42">Padrão 3 — Event Group como estado global, não evento</a><li><a href="#eb-table-content-43">Padrão 4 — Timer → Evento → Task</a><li><a href="#eb-table-content-44">Padrão 5 — Máquina de estados orientada a eventos</a><li><a href="#eb-table-content-45">Princípios arquiteturais que emergem</a><li><a href="#eb-table-content-46">Erros Arquiteturais Comuns e Como Evitá-los</a><li><a href="#eb-table-content-47">Erro 1 — Polling disfarçado de arquitetura orientada a eventos</a><li><a href="#eb-table-content-48">Erro 2 — Lógica pesada dentro de ISRs</a><li><a href="#erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos">Erro 3 — Uso excessivo de Event Groups como fila de eventos</a><li><a href="#eb-table-content-50">Erro 4 — Fila genérica para tudo</a><li><a href="#erro-5-tasks-que-nunca-bloqueiam">Erro 5 — Tasks que nunca bloqueiam</a><li><a href="#erro-6-misturar-estado-e-evento">Erro 6 — Misturar estado e evento</a><li><a href="#erro-7-overengineering-de-eventos">Erro 7 — Overengineering de eventos</a><li><a href="#eb-table-content-54">Checklist arquitetural prático</a><li><a href="#eb-table-content-55">Conclusão Técnica, Boas Práticas e Impacto no Projeto</a><li><a href="#eb-table-content-56">Boas práticas consolidadas</a><li><a href="#arquitetura-orientada-a-eventos-como-base-para-escalabilidade">Arquitetura orientada a eventos como base para escalabilidade</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading"><strong>Introdução e Motivação</strong></h3>



<p class="wp-block-paragraph">Em sistemas embarcados modernos, especialmente aqueles baseados em <strong>FreeRTOS</strong>, a forma como o firmware reage ao mundo externo é tão importante quanto o código em si. Sensores, comunicação, interrupções, timers e pilhas de protocolo geram estímulos de forma assíncrona, e arquiteturas tradicionais baseadas apenas em <em>superloop</em> rapidamente se tornam difíceis de manter, escalar e depurar. É nesse contexto que surge a <strong>Arquitetura Orientada a Eventos (Event-Driven Architecture – EDA)</strong>.</p>



<p class="wp-block-paragraph">No FreeRTOS, uma arquitetura orientada a eventos não é um “modo especial” do sistema operacional, mas sim uma <strong>estratégia de organização do firmware</strong>, onde tarefas permanecem bloqueadas aguardando eventos específicos e acordam apenas quando algo relevante ocorre. Esses eventos podem ser sinais de interrupção, mensagens, flags, notificações, timers ou dados disponíveis em buffers. O resultado é um sistema <strong>reativo, determinístico e eficiente em consumo de CPU</strong>.</p>



<p class="wp-block-paragraph">Do ponto de vista de engenharia, essa abordagem resolve três problemas clássicos:</p>



<ol class="wp-block-list">
<li><strong>Desperdício de CPU</strong> causado por polling constante</li>



<li><strong>Acoplamento excessivo</strong> entre módulos</li>



<li><strong>Dificuldade de sincronização</strong> entre múltiplas fontes de eventos</li>
</ol>



<p class="wp-block-paragraph">Ao adotar uma arquitetura orientada a eventos, o firmware passa a se comportar como um <strong>conjunto de agentes cooperativos</strong>, cada tarefa com responsabilidade clara, reagindo apenas aos eventos que lhe dizem respeito. Isso melhora a legibilidade do código, reduz latência média de resposta e facilita testes unitários e manutenção evolutiva.</p>



<p class="wp-block-paragraph">No FreeRTOS, essa arquitetura é viabilizada por um conjunto muito poderoso de primitivas nativas: <strong>Task Notifications</strong>, <strong>Queues</strong>, <strong>Event Groups</strong>, <strong>Stream Buffers</strong>, <strong>Message Buffers</strong> e <strong>Software Timers</strong>. Cada uma delas atende a um tipo específico de evento e será explorada detalhadamente ao longo deste artigo, sempre com exemplos práticos e contextualizados.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>O que vem a seguir</strong></h3>



<p class="wp-block-paragraph">Na próxima seção, entraremos no <strong>modelo conceitual da Arquitetura Orientada a Eventos no FreeRTOS</strong>, explicando como eventos fluem pelo sistema, como tarefas devem ser estruturadas e como evitar armadilhas comuns, como <em>event storms</em>, inversão de prioridade e acoplamento indireto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Modelo Conceitual da Arquitetura Orientada a Eventos</strong></h3>



<p class="wp-block-paragraph">Em uma arquitetura orientada a eventos no FreeRTOS, o sistema deixa de ser centrado em fluxo sequencial de execução e passa a ser organizado em torno de <strong>eventos que representam fatos relevantes do sistema</strong>. Um evento pode significar “um dado chegou”, “um tempo expirou”, “um periférico terminou uma operação” ou “uma condição de estado foi satisfeita”. O papel central do RTOS é <strong>suspender tarefas até que esses eventos ocorram</strong>, garantindo previsibilidade temporal e uso eficiente do processador.</p>



<p class="wp-block-paragraph">Do ponto de vista conceitual, essa arquitetura pode ser dividida em três elementos fundamentais: <strong>produtores de eventos</strong>, <strong>mecanismos de transporte de eventos</strong> e <strong>consumidores de eventos</strong>. Produtores normalmente são ISRs, timers de software, drivers ou tarefas de baixo nível. O transporte é feito pelas primitivas do FreeRTOS, enquanto os consumidores são tarefas que encapsulam lógica de negócio ou processamento de dados. Esse desacoplamento é essencial para sistemas escaláveis.</p>



<p class="wp-block-paragraph">Um princípio importante é que <strong>tarefas orientadas a eventos devem permanecer bloqueadas na maior parte do tempo</strong>. Em FreeRTOS, isso significa usar chamadas bloqueantes como <code>xQueueReceive()</code>, <code>xEventGroupWaitBits()</code> ou <code>ulTaskNotifyTake()</code>, sempre com <code>portMAX_DELAY</code> ou tempos bem definidos. Dessa forma, não há polling ativo, e o escalonador pode dedicar CPU apenas às tarefas que realmente precisam executar naquele instante.</p>



<p class="wp-block-paragraph">Outro ponto crítico do modelo é que <strong>eventos não devem carregar lógica</strong>, apenas sinalização e dados mínimos. A decisão do que fazer em resposta a um evento pertence à tarefa consumidora. Isso evita que ISRs fiquem complexas e garante que decisões de alto nível ocorram sempre em contexto de tarefa, onde mutexes, alocação de memória e chamadas de API são seguras.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Fluxo típico de eventos no FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Um fluxo clássico em arquitetura orientada a eventos segue o seguinte encadeamento lógico:</p>



<ol class="wp-block-list">
<li>Um periférico gera uma interrupção (por exemplo, UART RX completa).</li>



<li>A ISR sinaliza o evento usando uma primitiva segura para interrupções.</li>



<li>O kernel do FreeRTOS desbloqueia a tarefa interessada.</li>



<li>A tarefa acorda, processa o evento e retorna ao estado bloqueado.</li>
</ol>



<p class="wp-block-paragraph">Esse modelo cria um sistema <strong>reativo e previsível</strong>, onde a latência entre o evento e o processamento é controlada diretamente pela prioridade da tarefa e pela duração das ISRs. Em projetos bem arquitetados, o tempo gasto dentro da interrupção é mínimo, e todo o processamento ocorre em nível de tarefa.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Exemplo conceitual simplificado</strong></h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void vUartTask(void *pvParameters)
{
    uint8_t rxByte;

    for (;;)
    {
        if (xQueueReceive(uartRxQueue, &amp;rxByte, portMAX_DELAY) == pdPASS)
        {
            processUartByte(rxByte);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vUartTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uartRxQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">processUartByte</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rxByte</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Neste exemplo, a tarefa <code>vUartTask</code> não executa continuamente. Ela permanece bloqueada até que um byte seja colocado na fila por uma ISR ou outra tarefa. Isso caracteriza perfeitamente o modelo orientado a eventos: <strong>o evento é a chegada de um dado</strong>, e a tarefa existe apenas para reagir a ele.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Implicações arquiteturais importantes</strong></h3>



<p class="wp-block-paragraph">Ao adotar esse modelo, algumas decisões de projeto tornam-se fundamentais. A granularidade dos eventos deve ser cuidadosamente escolhida: eventos muito genéricos levam a tarefas complexas e difíceis de testar; eventos excessivamente específicos geram sobrecarga e fragmentação. Além disso, o uso correto de prioridades é crucial para garantir que eventos críticos sejam tratados com menor latência.</p>



<p class="wp-block-paragraph">Outro aspecto frequentemente negligenciado é o tratamento de <strong>eventos concorrentes</strong>. O FreeRTOS permite que múltiplos eventos acordem a mesma tarefa, mas o firmware deve ser capaz de lidar com isso de forma determinística, normalmente utilizando estruturas de estado bem definidas ou <em>state machines</em> orientadas a eventos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na <strong>próxima seção</strong>, entraremos nos <strong>mecanismos de eventos disponíveis no FreeRTOS</strong>, começando pelo mais eficiente e subutilizado deles: <strong>Task Notifications</strong>, analisando seu funcionamento interno, vantagens, limitações e padrões de uso.</p>



<p class="wp-block-paragraph">Excelente, seguimos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Task Notifications como Mecanismo Central de Eventos</strong></h3>



<p class="wp-block-paragraph">Entre todos os mecanismos oferecidos pelo FreeRTOS, as <strong>Task Notifications</strong> são, do ponto de vista arquitetural, a forma mais eficiente de implementar uma arquitetura orientada a eventos. Elas funcionam como um <strong>canal direto ponto-a-ponto entre o kernel e uma tarefa</strong>, sem a sobrecarga de filas, sem alocação dinâmica e com latência mínima.</p>



<p class="wp-block-paragraph">Cada tarefa no FreeRTOS possui internamente um <strong>array de notificações</strong> (desde o FreeRTOS 10), onde cada entrada contém um valor de 32 bits e um estado. Isso transforma a task notification em algo conceitualmente próximo a um <strong>registrador de eventos privado da tarefa</strong>. Esse detalhe é fundamental para entender por que esse mecanismo é tão eficiente e, ao mesmo tempo, tão poderoso.</p>



<p class="wp-block-paragraph">Diferente de filas ou event groups, <strong>uma task notification não é compartilhada</strong>. Ela pertence a uma única tarefa. Isso força uma arquitetura mais limpa, onde existe um mapeamento explícito entre <em>quem produz</em> e <em>quem consome</em> o evento. Em arquiteturas bem desenhadas, isso reduz drasticamente o acoplamento implícito e elimina ambiguidades.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Modelo mental correto para Task Notifications</strong></h3>



<p class="wp-block-paragraph">É comum iniciantes tratarem task notifications como “um semáforo mais rápido”. Embora isso seja parcialmente verdadeiro, essa visão é limitada. O modelo correto é pensar nelas como:</p>



<ul class="wp-block-list">
<li>Um <strong>evento binário</strong> (acordar ou não acordar a task)</li>



<li>Um <strong>contador</strong> (quantidade de eventos acumulados)</li>



<li>Um <strong>bitmap de flags</strong></li>



<li>Um <strong>payload de 32 bits</strong></li>
</ul>



<p class="wp-block-paragraph">Tudo isso usando a <strong>mesma infraestrutura</strong>, dependendo apenas da API utilizada.</p>



<p class="wp-block-paragraph">Essa flexibilidade permite criar arquiteturas orientadas a eventos extremamente compactas, onde um único mecanismo substitui filas, semáforos e flags em muitos cenários.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Exemplo 1 — Evento simples (sinalização pura)</strong></h3>



<p class="wp-block-paragraph">Neste primeiro exemplo, uma ISR sinaliza que um evento ocorreu, e a tarefa apenas reage.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void vEventTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        handleEvent();
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vEventTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">ulTaskNotifyTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pdTRUE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">handleEvent</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">A função <code>ulTaskNotifyTake()</code> bloqueia a tarefa até que uma notificação seja recebida. O parâmetro <code>pdTRUE</code> indica que o contador interno será limpo ao acordar, garantindo comportamento de evento simples.</p>



<p class="wp-block-paragraph">A ISR responsável pelo evento:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void EXTI_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    vTaskNotifyGiveFromISR(eventTaskHandle, &amp;xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EXTI_IRQHandler</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">BaseType_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdFALSE</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vTaskNotifyGiveFromISR</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">eventTaskHandle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">portYIELD_FROM_ISR</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xHigherPriorityTaskWoken</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Aqui, o evento é produzido de forma segura em contexto de interrupção, e o kernel pode realizar <em>context switch</em> imediato se a prioridade justificar. Esse padrão é ideal para eventos como botão pressionado, fim de conversão ADC ou término de DMA.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Exemplo 2 — Contador de eventos acumulados</strong></h3>



<p class="wp-block-paragraph">Em cenários onde múltiplos eventos podem ocorrer antes da tarefa acordar, a task notification pode atuar como <strong>contador</strong>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void vLoggerTask(void *pvParameters)
{
    uint32_t events;

    for (;;)
    {
        events = ulTaskNotifyTake(pdFALSE, portMAX_DELAY);

        while (events--)
        {
            logEvent();
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vLoggerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">events</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ulTaskNotifyTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pdFALSE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">events</span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">logEvent</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Ao usar <code>pdFALSE</code>, o contador não é automaticamente zerado. O valor retornado indica quantos eventos ocorreram desde a última leitura. Isso é extremamente útil em sistemas com bursts de eventos, como recepção de pacotes ou amostras rápidas de sensores.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Exemplo 3 — Task Notification como bitmap de eventos</strong></h3>



<p class="wp-block-paragraph">Outra aplicação avançada é usar o valor de 32 bits como <strong>mapa de bits de eventos</strong>, substituindo completamente os Event Groups quando o evento é destinado a uma única tarefa.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#define EVT_RX_READY   (1 &lt;&lt; 0)
#define EVT_TX_DONE   (1 &lt;&lt; 1)
#define EVT_ERROR     (1 &lt;&lt; 2)

void vCommTask(void *pvParameters)
{
    uint32_t events;

    for (;;)
    {
        xTaskNotifyWait(0x00, 0xFFFFFFFF, &amp;events, portMAX_DELAY);

        if (events &amp; EVT_RX_READY)
            handleRx();

        if (events &amp; EVT_TX_DONE)
            handleTxDone();

        if (events &amp; EVT_ERROR)
            handleError();
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EVT_RX_READY</span><span style="color: #D8DEE9FF">   (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EVT_TX_DONE</span><span style="color: #D8DEE9FF">   (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">EVT_ERROR</span><span style="color: #D8DEE9FF">     (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vCommTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">events</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskNotifyWait</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">0x00</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0xFFFFFFFF</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">events</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_RX_READY</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">handleRx</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_TX_DONE</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">handleTxDone</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVT_ERROR</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">handleError</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse padrão cria uma <strong>máquina de eventos compacta</strong>, extremamente eficiente e fácil de analisar em termos de latência e consumo de recursos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Vantagens arquiteturais das Task Notifications</strong></h3>



<p class="wp-block-paragraph">Do ponto de vista de engenharia de sistemas, as task notifications oferecem:</p>



<ul class="wp-block-list">
<li>Menor latência entre evento e execução</li>



<li>Zero uso de heap</li>



<li>Menor footprint de memória</li>



<li>Determinismo temporal elevado</li>



<li>Código mais explícito e fácil de rastrear</li>
</ul>



<p class="wp-block-paragraph">Por esse motivo, em arquiteturas orientadas a eventos bem projetadas, <strong>task notifications devem ser a primeira opção</strong>, e não a última.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Na <strong>próxima seção</strong>, vamos tratar de <strong>Event Groups</strong>, explicando quando eles são necessários, como evitá-los em excesso e como integrá-los corretamente em uma arquitetura orientada a eventos sem criar dependências implícitas.</p>



<p class="wp-block-paragraph">Seguimos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/">Arquitetura Orientada a Eventos no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1057</post-id>	</item>
		<item>
		<title>FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</title>
		<link>https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 13 Feb 2026 16:10:46 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[buffers circulares]]></category>
		<category><![CDATA[comunicação entre tarefas]]></category>
		<category><![CDATA[desempenho em tempo real]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[ISR FreeRTOS]]></category>
		<category><![CDATA[producer consumer]]></category>
		<category><![CDATA[queue FreeRTOS]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stream buffer]]></category>
		<category><![CDATA[UART FreeRTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1050</guid>

					<description><![CDATA[<p>Neste artigo técnico e didático, exploramos em profundidade o uso de Stream Buffers no FreeRTOS, explicando seu funcionamento interno, comparando-os detalhadamente com Queues e apresentando critérios claros para escolher o mecanismo correto em sistemas embarcados. O conteúdo aborda desempenho, latência, uso de memória, topologia produtor–consumidor, boas práticas, armadilhas comuns e exemplos de código em C voltados a aplicações reais como UART, sensores e pipelines de dados em tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/">FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-x3mpg wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-x3mpg "><div class="eb-toc-container eb-toc-x3mpg  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;text&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;text&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;text&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;link&quot;:&quot;exemplo-de-escrita-em-uma-tarefa-produtora&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;text&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;link&quot;:&quot;exemplo-de-leitura-em-uma-tarefa-consumidora&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;text&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;link&quot;:&quot;queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;text&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Envio de dados para a Queue&quot;,&quot;text&quot;:&quot;Envio de dados para a Queue&quot;,&quot;link&quot;:&quot;envio-de-dados-para-a-queue&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;text&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Custos ocultos das Queues&quot;,&quot;text&quot;:&quot;Custos ocultos das Queues&quot;,&quot;link&quot;:&quot;custos-ocultos-das-queues&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;text&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;text&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;text&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;link&quot;:&quot;exemplo-comparativo-uart-rx&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;text&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;text&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;link&quot;:&quot;armadilha-1-tratar-stream-buffer-como-message-queue&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;text&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;text&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;link&quot;:&quot;armadilha-3-usar-delays-em-vez-de-bloqueio&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;text&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-comunica\u00e7\u00e3o-entre-tarefas-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;value&quot;:&quot;o-que-s\u00e3o-stream-buffers-no-freertos-e-como-eles-funcionam-internamente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;value&quot;:&quot;exemplo-b\u00e1sico-cria\u00e7\u00e3o-de-um-stream-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;value&quot;:&quot;exemplo-de-escrita-em-uma-tarefa-produtora&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;value&quot;:&quot;exemplo-de-leitura-em-uma-tarefa-consumidora&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;value&quot;:&quot;queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;value&quot;:&quot;exemplo-b\u00e1sico-cria\u00e7\u00e3o-de-uma-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Envio de dados para a Queue&quot;,&quot;value&quot;:&quot;envio-de-dados-para-a-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;value&quot;:&quot;recep\u00e7\u00e3o-de-dados-da-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Custos ocultos das Queues&quot;,&quot;value&quot;:&quot;custos-ocultos-das-queues&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;value&quot;:&quot;stream-buffers-vs-queues-compara\u00e7\u00e3o-t\u00e9cnica-detalhada-e-crit\u00e9rios-de-escolha&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;value&quot;:&quot;compara\u00e7\u00e3o-estrutural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;value&quot;:&quot;crit\u00e9rio-1-natureza-do-dado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;value&quot;:&quot;crit\u00e9rio-2-desempenho-e-lat\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;value&quot;:&quot;crit\u00e9rio-3-topologia-produtorconsumidor&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;value&quot;:&quot;exemplo-comparativo-uart-rx&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-uso-boas-pr\u00e1ticas-e-armadilhas-comuns-com-stream-buffers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-1-dimensionamento-correto-do-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-2-uso-consciente-do-trigger-level&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-3-sempre-respeitar-o-modelo-1\u21921&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;value&quot;:&quot;armadilha-1-tratar-stream-buffer-como-message-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;value&quot;:&quot;armadilha-2-ignorar-retornos-das-fun\u00e7\u00f5es&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;value&quot;:&quot;armadilha-3-usar-delays-em-vez-de-bloqueio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;value&quot;:&quot;conclus\u00e3o-t\u00e9cnica-e-diretrizes-finais-de-projeto&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução: comunicação entre tarefas no FreeRTOS</a><li><a href="#eb-table-content-1">O que são Stream Buffers no FreeRTOS e como eles funcionam internamente</a><ul class="eb-toc__list"><li><a href="#eb-table-content-2">Exemplo básico: criação de um Stream Buffer</a><li><a href="#exemplo-de-escrita-em-uma-tarefa-produtora">Exemplo de escrita em uma tarefa produtora</a><li><a href="#exemplo-de-leitura-em-uma-tarefa-consumidora">Exemplo de leitura em uma tarefa consumidora</a></li></ul><li><a href="#queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos">Queues no FreeRTOS: modelo de dados, garantias e custos ocultos</a><ul class="eb-toc__list"><li><a href="#eb-table-content-6">Exemplo básico: criação de uma Queue</a><li><a href="#envio-de-dados-para-a-queue">Envio de dados para a Queue</a><li><a href="#eb-table-content-8">Recepção de dados da Queue</a><li><a href="#custos-ocultos-das-queues">Custos ocultos das Queues</a></li></ul><li><a href="#eb-table-content-10">Stream Buffers vs Queues: comparação técnica detalhada e critérios de escolha</a><ul class="eb-toc__list"><li><a href="#eb-table-content-11">Comparação estrutural</a><li><a href="#eb-table-content-12">Critério 1: natureza do dado</a><li><a href="#eb-table-content-13">Critério 2: desempenho e latência</a><li><a href="#eb-table-content-14">Critério 3: topologia produtor–consumidor</a><li><a href="#exemplo-comparativo-uart-rx">Exemplo comparativo: UART RX</a></li></ul><li><a href="#eb-table-content-16">Padrões de uso, boas práticas e armadilhas comuns com Stream Buffers</a><ul class="eb-toc__list"><li><a href="#eb-table-content-17">Boa prática 1: dimensionamento correto do buffer</a><li><a href="#eb-table-content-18">Boa prática 2: uso consciente do trigger level</a><li><a href="#eb-table-content-19">Boa prática 3: sempre respeitar o modelo 1→1</a><li><a href="#armadilha-1-tratar-stream-buffer-como-message-queue">Armadilha 1: tratar Stream Buffer como Message Queue</a><li><a href="#eb-table-content-21">Armadilha 2: ignorar retornos das funções</a><li><a href="#armadilha-3-usar-delays-em-vez-de-bloqueio">Armadilha 3: usar delays em vez de bloqueio</a></li></ul><li><a href="#eb-table-content-23">Conclusão técnica e diretrizes finais de projeto</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading"><strong>Introdução: comunicação entre tarefas no FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Em sistemas embarcados baseados em <em>Real-Time Operating Systems</em> (RTOS), a comunicação entre tarefas (<em>tasks</em>) e entre interrupções (<em>ISRs – Interrupt Service Routines</em>) é um dos pilares da arquitetura de software. No FreeRTOS, essa comunicação pode ocorrer por diversos mecanismos: <em>queues</em>, <em>semaphores</em>, <em>event groups</em>, <em>task notifications</em> e, mais recentemente, <em>stream buffers</em> e <em>message buffers</em>. Cada um desses mecanismos foi projetado para atender a padrões específicos de troca de dados, com impactos diretos em desempenho, uso de memória, latência e complexidade do código.</p>



<p class="wp-block-paragraph">Historicamente, as <em>queues</em> foram o principal mecanismo para troca de dados entre tarefas no FreeRTOS. Elas oferecem uma semântica clara, segura e genérica, permitindo o envio de estruturas de dados completas entre produtores e consumidores. No entanto, conforme sistemas embarcados passaram a lidar com <strong>fluxos contínuos de dados</strong> — como áudio, streams de sensores, bytes vindos de UART, SPI, USB ou stacks de rede —, tornou-se evidente que o modelo tradicional de <em>queue</em> não era o mais eficiente para esse tipo de cenário.</p>



<p class="wp-block-paragraph">É nesse contexto que surgem os <strong>Stream Buffers</strong>, introduzidos para lidar com <strong>dados orientados a fluxo</strong>, onde o mais importante não é a fronteira entre mensagens, mas sim a sequência contínua de bytes. Diferentemente das <em>queues</em>, que operam com itens discretos e de tamanho fixo, os <em>stream buffers</em> operam como um <strong>buffer circular de bytes</strong>, permitindo escrita e leitura parcial, com controle fino sobre bloqueio, timeout e sincronização entre tarefas e ISRs.</p>



<p class="wp-block-paragraph">Nesta série de artigos sobre FreeRTOS, esta seção tem como objetivo introduzir formalmente o conceito de <em>stream buffers</em>, posicioná-los corretamente dentro do ecossistema de mecanismos de comunicação do sistema operacional e preparar o terreno para uma comparação técnica aprofundada com <em>queues</em>. Ao longo das próximas seções, veremos <strong>como funcionam internamente</strong>, <strong>quando usá-los</strong>, <strong>quando evitá-los</strong> e <strong>como escrever código eficiente e seguro</strong> usando esse recurso.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/">FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1050</post-id>	</item>
		<item>
		<title>ISR + RTOS na Prática com FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/isr-rtos-na-pratica-com-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=isr-rtos-na-pratica-com-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 06 Feb 2026 13:37:54 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[comunicação ISR task]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[FreeRTOS boas práticas]]></category>
		<category><![CDATA[freeRTOS cortex-m]]></category>
		<category><![CDATA[FreeRTOS tempo real]]></category>
		<category><![CDATA[interrupções em sistemas embarcados]]></category>
		<category><![CDATA[ISR]]></category>
		<category><![CDATA[ISR FromISR]]></category>
		<category><![CDATA[prioridades NVIC FreeRTOS]]></category>
		<category><![CDATA[RTOS em microcontroladores]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1044</guid>

					<description><![CDATA[<p>Entenda como integrar corretamente rotinas de interrupção (ISR) ao FreeRTOS em sistemas embarcados. Aprenda o uso das APIs FromISR, prioridades de interrupção no Cortex-M, comunicação ISR → Task, boas práticas arquiteturais, erros comuns e técnicas profissionais de debug para sistemas tempo real determinísticos e robustos.</p>
<p>The post <a href="https://mcu.tec.br/rtos/isr-rtos-na-pratica-com-freertos/">ISR + RTOS na Prática com FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-g555h wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-g555h "><div class="eb-toc-container eb-toc-g555h  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;O modelo de execu\u00e7\u00e3o do FreeRTOS e o papel das interrup\u00e7\u00f5es&quot;,&quot;text&quot;:&quot;O modelo de execu\u00e7\u00e3o do FreeRTOS e o papel das interrup\u00e7\u00f5es&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;APIs FromISR: por que elas existem e como funcionam&quot;,&quot;text&quot;:&quot;APIs FromISR: por que elas existem e como funcionam&quot;,&quot;link&quot;:&quot;apis-fromisr-por-que-elas-existem-e-como-funcionam&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Motiva\u00e7\u00e3o conceitual&quot;,&quot;text&quot;:&quot;Motiva\u00e7\u00e3o conceitual&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;O par\u00e2metro xHigherPriorityTaskWoken&quot;,&quot;text&quot;:&quot;O par\u00e2metro xHigherPriorityTaskWoken&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Por que n\u00e3o chamar o escalonador diretamente?&quot;,&quot;text&quot;:&quot;Por que n\u00e3o chamar o escalonador diretamente?&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Resumo pr\u00e1tico desta se\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Resumo pr\u00e1tico desta se\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Comunica\u00e7\u00e3o entre ISR e Tasks: qual mecanismo usar e quando&quot;,&quot;text&quot;:&quot;Comunica\u00e7\u00e3o entre ISR e Tasks: qual mecanismo usar e quando&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 Sem\u00e1foros bin\u00e1rios: sinaliza\u00e7\u00e3o simples de eventos&quot;,&quot;text&quot;:&quot;4.1 Sem\u00e1foros bin\u00e1rios: sinaliza\u00e7\u00e3o simples de eventos&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Filas (Queues): eventos com dados&quot;,&quot;text&quot;:&quot;4.2 Filas (Queues): eventos com dados&quot;,&quot;link&quot;:&quot;42-filas-queues-eventos-com-dados&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Notifica\u00e7\u00f5es diretas de task: o mecanismo mais eficiente&quot;,&quot;text&quot;:&quot;4.3 Notifica\u00e7\u00f5es diretas de task: o mecanismo mais eficiente&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Event Groups: m\u00faltiplos eventos e sincroniza\u00e7\u00e3o complexa&quot;,&quot;text&quot;:&quot;4.4 Event Groups: m\u00faltiplos eventos e sincroniza\u00e7\u00e3o complexa&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Resumo arquitetural&quot;,&quot;text&quot;:&quot;Resumo arquitetural&quot;,&quot;link&quot;:&quot;resumo-arquitetural&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Prioridades de interrup\u00e7\u00e3o no Cortex-M e regras do FreeRTOS&quot;,&quot;text&quot;:&quot;Prioridades de interrup\u00e7\u00e3o no Cortex-M e regras do FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Como o NVIC trata prioridades de interrup\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;5.1 Como o NVIC trata prioridades de interrup\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 O papel de configMAX_SYSCALL_INTERRUPT_PRIORITY&quot;,&quot;text&quot;:&quot;5.2 O papel de configMAX_SYSCALL_INTERRUPT_PRIORITY&quot;,&quot;link&quot;:&quot;52-o-papel-de-configmax_syscall_interrupt_priority&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Erro cl\u00e1ssico: \u201cfunciona at\u00e9 parar de funcionar\u201d&quot;,&quot;text&quot;:&quot;5.3 Erro cl\u00e1ssico: \u201cfunciona at\u00e9 parar de funcionar\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Regra de ouro para Cortex-M + FreeRTOS&quot;,&quot;text&quot;:&quot;5.4 Regra de ouro para Cortex-M + FreeRTOS&quot;,&quot;link&quot;:&quot;54-regra-de-ouro-para-cortex-m-freertos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Configura\u00e7\u00e3o correta no c\u00f3digo&quot;,&quot;text&quot;:&quot;5.5 Configura\u00e7\u00e3o correta no c\u00f3digo&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Por que o FreeRTOS faz isso?&quot;,&quot;text&quot;:&quot;5.6 Por que o FreeRTOS faz isso?&quot;,&quot;link&quot;:&quot;56-por-que-o-freertos-faz-isso&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Boas pr\u00e1ticas e padr\u00f5es arquiteturais para ISR + FreeRTOS&quot;,&quot;text&quot;:&quot;Boas pr\u00e1ticas e padr\u00f5es arquiteturais para ISR + FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 ISR m\u00ednima: a regra mais importante&quot;,&quot;text&quot;:&quot;6.1 ISR m\u00ednima: a regra mais importante&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Deferred Interrupt Processing (DIP)&quot;,&quot;text&quot;:&quot;6.2 Deferred Interrupt Processing (DIP)&quot;,&quot;link&quot;:&quot;62-deferred-interrupt-processing-dip&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Escolha correta do mecanismo de sinaliza\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;6.3 Escolha correta do mecanismo de sinaliza\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-22&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 ISR n\u00e3o \u00e9 lugar para HAL complexa&quot;,&quot;text&quot;:&quot;6.4 ISR n\u00e3o \u00e9 lugar para HAL complexa&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.5 Prioridades de tasks e interrup\u00e7\u00f5es alinhadas&quot;,&quot;text&quot;:&quot;6.5 Prioridades de tasks e interrup\u00e7\u00f5es alinhadas&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.6 Checklist profissional ISR + FreeRTOS&quot;,&quot;text&quot;:&quot;6.6 Checklist profissional ISR + FreeRTOS&quot;,&quot;link&quot;:&quot;66-checklist-profissional-isr-freertos&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Erros comuns, sintomas e estrat\u00e9gias de debug em ISR + FreeRTOS&quot;,&quot;text&quot;:&quot;Erros comuns, sintomas e estrat\u00e9gias de debug em ISR + FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-26&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.1 Sintoma: sistema \u201ccongela\u201d aleatoriamente&quot;,&quot;text&quot;:&quot;7.1 Sintoma: sistema \u201ccongela\u201d aleatoriamente&quot;,&quot;link&quot;:&quot;71-sintoma-sistema-congela-aleatoriamente&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.2 Sintoma: eventos perdidos ou atrasados&quot;,&quot;text&quot;:&quot;7.2 Sintoma: eventos perdidos ou atrasados&quot;,&quot;link&quot;:&quot;72-sintoma-eventos-perdidos-ou-atrasados&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.3 Sintoma: jitter elevado em tarefas de controle&quot;,&quot;text&quot;:&quot;7.3 Sintoma: jitter elevado em tarefas de controle&quot;,&quot;link&quot;:&quot;73-sintoma-jitter-elevado-em-tarefas-de-controle&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.4 Uso de GPIO para an\u00e1lise temporal (t\u00e9cnica profissional)&quot;,&quot;text&quot;:&quot;7.4 Uso de GPIO para an\u00e1lise temporal (t\u00e9cnica profissional)&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.5 Assertivas do FreeRTOS: aliadas, n\u00e3o inimigas&quot;,&quot;text&quot;:&quot;7.5 Assertivas do FreeRTOS: aliadas, n\u00e3o inimigas&quot;,&quot;link&quot;:&quot;eb-table-content-31&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.6 Anti-padr\u00f5es cl\u00e1ssicos (resumo r\u00e1pido)&quot;,&quot;text&quot;:&quot;7.6 Anti-padr\u00f5es cl\u00e1ssicos (resumo r\u00e1pido)&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.7 Mentalidade correta: ISR como fronteira de tempo real&quot;,&quot;text&quot;:&quot;7.7 Mentalidade correta: ISR como fronteira de tempo real&quot;,&quot;link&quot;:&quot;77-mentalidade-correta-isr-como-fronteira-de-tempo-real&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Conclus\u00e3o \u2013 ISR + FreeRTOS como arquitetura, n\u00e3o como detalhe&quot;,&quot;text&quot;:&quot;Conclus\u00e3o \u2013 ISR + FreeRTOS como arquitetura, n\u00e3o como detalhe&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;O modelo de execu\u00e7\u00e3o do FreeRTOS e o papel das interrup\u00e7\u00f5es&quot;,&quot;value&quot;:&quot;o-modelo-de-execu\u00e7\u00e3o-do-freertos-e-o-papel-das-interrup\u00e7\u00f5es&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;APIs FromISR: por que elas existem e como funcionam&quot;,&quot;value&quot;:&quot;apis-fromisr-por-que-elas-existem-e-como-funcionam&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Motiva\u00e7\u00e3o conceitual&quot;,&quot;value&quot;:&quot;motiva\u00e7\u00e3o-conceitual&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O par\u00e2metro xHigherPriorityTaskWoken&quot;,&quot;value&quot;:&quot;o-par\u00e2metro-xhigherprioritytaskwoken&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Por que n\u00e3o chamar o escalonador diretamente?&quot;,&quot;value&quot;:&quot;por-que-n\u00e3o-chamar-o-escalonador-diretamente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Resumo pr\u00e1tico desta se\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;resumo-pr\u00e1tico-desta-se\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Comunica\u00e7\u00e3o entre ISR e Tasks: qual mecanismo usar e quando&quot;,&quot;value&quot;:&quot;comunica\u00e7\u00e3o-entre-isr-e-tasks-qual-mecanismo-usar-e-quando&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 Sem\u00e1foros bin\u00e1rios: sinaliza\u00e7\u00e3o simples de eventos&quot;,&quot;value&quot;:&quot;41-sem\u00e1foros-bin\u00e1rios-sinaliza\u00e7\u00e3o-simples-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Filas (Queues): eventos com dados&quot;,&quot;value&quot;:&quot;42-filas-queues-eventos-com-dados&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Notifica\u00e7\u00f5es diretas de task: o mecanismo mais eficiente&quot;,&quot;value&quot;:&quot;43-notifica\u00e7\u00f5es-diretas-de-task-o-mecanismo-mais-eficiente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Event Groups: m\u00faltiplos eventos e sincroniza\u00e7\u00e3o complexa&quot;,&quot;value&quot;:&quot;44-event-groups-m\u00faltiplos-eventos-e-sincroniza\u00e7\u00e3o-complexa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Resumo arquitetural&quot;,&quot;value&quot;:&quot;resumo-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Prioridades de interrup\u00e7\u00e3o no Cortex-M e regras do FreeRTOS&quot;,&quot;value&quot;:&quot;prioridades-de-interrup\u00e7\u00e3o-no-cortex-m-e-regras-do-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Como o NVIC trata prioridades de interrup\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;51-como-o-nvic-trata-prioridades-de-interrup\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 O papel de configMAX_SYSCALL_INTERRUPT_PRIORITY&quot;,&quot;value&quot;:&quot;52-o-papel-de-configmax_syscall_interrupt_priority&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Erro cl\u00e1ssico: \u201cfunciona at\u00e9 parar de funcionar\u201d&quot;,&quot;value&quot;:&quot;53-erro-cl\u00e1ssico-funciona-at\u00e9-parar-de-funcionar&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Regra de ouro para Cortex-M + FreeRTOS&quot;,&quot;value&quot;:&quot;54-regra-de-ouro-para-cortex-m-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Configura\u00e7\u00e3o correta no c\u00f3digo&quot;,&quot;value&quot;:&quot;55-configura\u00e7\u00e3o-correta-no-c\u00f3digo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Por que o FreeRTOS faz isso?&quot;,&quot;value&quot;:&quot;56-por-que-o-freertos-faz-isso&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boas pr\u00e1ticas e padr\u00f5es arquiteturais para ISR + FreeRTOS&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-e-padr\u00f5es-arquiteturais-para-isr-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 ISR m\u00ednima: a regra mais importante&quot;,&quot;value&quot;:&quot;61-isr-m\u00ednima-a-regra-mais-importante&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Deferred Interrupt Processing (DIP)&quot;,&quot;value&quot;:&quot;62-deferred-interrupt-processing-dip&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Escolha correta do mecanismo de sinaliza\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;63-escolha-correta-do-mecanismo-de-sinaliza\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 ISR n\u00e3o \u00e9 lugar para HAL complexa&quot;,&quot;value&quot;:&quot;64-isr-n\u00e3o-\u00e9-lugar-para-hal-complexa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.5 Prioridades de tasks e interrup\u00e7\u00f5es alinhadas&quot;,&quot;value&quot;:&quot;65-prioridades-de-tasks-e-interrup\u00e7\u00f5es-alinhadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.6 Checklist profissional ISR + FreeRTOS&quot;,&quot;value&quot;:&quot;66-checklist-profissional-isr-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erros comuns, sintomas e estrat\u00e9gias de debug em ISR + FreeRTOS&quot;,&quot;value&quot;:&quot;erros-comuns-sintomas-e-estrat\u00e9gias-de-debug-em-isr-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.1 Sintoma: sistema \u201ccongela\u201d aleatoriamente&quot;,&quot;value&quot;:&quot;71-sintoma-sistema-congela-aleatoriamente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.2 Sintoma: eventos perdidos ou atrasados&quot;,&quot;value&quot;:&quot;72-sintoma-eventos-perdidos-ou-atrasados&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.3 Sintoma: jitter elevado em tarefas de controle&quot;,&quot;value&quot;:&quot;73-sintoma-jitter-elevado-em-tarefas-de-controle&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.4 Uso de GPIO para an\u00e1lise temporal (t\u00e9cnica profissional)&quot;,&quot;value&quot;:&quot;74-uso-de-gpio-para-an\u00e1lise-temporal-t\u00e9cnica-profissional&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.5 Assertivas do FreeRTOS: aliadas, n\u00e3o inimigas&quot;,&quot;value&quot;:&quot;75-assertivas-do-freertos-aliadas-n\u00e3o-inimigas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.6 Anti-padr\u00f5es cl\u00e1ssicos (resumo r\u00e1pido)&quot;,&quot;value&quot;:&quot;76-anti-padr\u00f5es-cl\u00e1ssicos-resumo-r\u00e1pido&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.7 Mentalidade correta: ISR como fronteira de tempo real&quot;,&quot;value&quot;:&quot;77-mentalidade-correta-isr-como-fronteira-de-tempo-real&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o \u2013 ISR + FreeRTOS como arquitetura, n\u00e3o como detalhe&quot;,&quot;value&quot;:&quot;conclus\u00e3o-isr-freertos-como-arquitetura-n\u00e3o-como-detalhe&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">O modelo de execução do FreeRTOS e o papel das interrupções</a><li><a href="#apis-fromisr-por-que-elas-existem-e-como-funcionam">APIs FromISR: por que elas existem e como funcionam</a><ul class="eb-toc__list"><li><a href="#eb-table-content-2">Motivação conceitual</a><li><a href="#eb-table-content-3">O parâmetro xHigherPriorityTaskWoken</a><li><a href="#eb-table-content-4">Por que não chamar o escalonador diretamente?</a><li><a href="#eb-table-content-5">Resumo prático desta seção</a></li></ul><li><a href="#eb-table-content-6">Comunicação entre ISR e Tasks: qual mecanismo usar e quando</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">4.1 Semáforos binários: sinalização simples de eventos</a><li><a href="#42-filas-queues-eventos-com-dados">4.2 Filas (Queues): eventos com dados</a><li><a href="#eb-table-content-9">4.3 Notificações diretas de task: o mecanismo mais eficiente</a><li><a href="#eb-table-content-10">4.4 Event Groups: múltiplos eventos e sincronização complexa</a><li><a href="#resumo-arquitetural">Resumo arquitetural</a></li></ul><li><a href="#eb-table-content-12">Prioridades de interrupção no Cortex-M e regras do FreeRTOS</a><ul class="eb-toc__list"><li><a href="#eb-table-content-13">5.1 Como o NVIC trata prioridades de interrupção</a><li><a href="#52-o-papel-de-configmax_syscall_interrupt_priority">5.2 O papel de configMAX_SYSCALL_INTERRUPT_PRIORITY</a><li><a href="#eb-table-content-15">5.3 Erro clássico: “funciona até parar de funcionar”</a><li><a href="#54-regra-de-ouro-para-cortex-m-freertos">5.4 Regra de ouro para Cortex-M + FreeRTOS</a><li><a href="#eb-table-content-17">5.5 Configuração correta no código</a><li><a href="#56-por-que-o-freertos-faz-isso">5.6 Por que o FreeRTOS faz isso?</a></li></ul><li><a href="#eb-table-content-19">Boas práticas e padrões arquiteturais para ISR + FreeRTOS</a><ul class="eb-toc__list"><li><a href="#eb-table-content-20">6.1 ISR mínima: a regra mais importante</a><li><a href="#62-deferred-interrupt-processing-dip">6.2 Deferred Interrupt Processing (DIP)</a><li><a href="#eb-table-content-22">6.3 Escolha correta do mecanismo de sinalização</a><li><a href="#eb-table-content-23">6.4 ISR não é lugar para HAL complexa</a><li><a href="#eb-table-content-24">6.5 Prioridades de tasks e interrupções alinhadas</a><li><a href="#66-checklist-profissional-isr-freertos">6.6 Checklist profissional ISR + FreeRTOS</a></li></ul><li><a href="#eb-table-content-26">Erros comuns, sintomas e estratégias de debug em ISR + FreeRTOS</a><ul class="eb-toc__list"><li><a href="#71-sintoma-sistema-congela-aleatoriamente">7.1 Sintoma: sistema “congela” aleatoriamente</a><li><a href="#72-sintoma-eventos-perdidos-ou-atrasados">7.2 Sintoma: eventos perdidos ou atrasados</a><li><a href="#73-sintoma-jitter-elevado-em-tarefas-de-controle">7.3 Sintoma: jitter elevado em tarefas de controle</a><li><a href="#eb-table-content-30">7.4 Uso de GPIO para análise temporal (técnica profissional)</a><li><a href="#eb-table-content-31">7.5 Assertivas do FreeRTOS: aliadas, não inimigas</a><li><a href="#eb-table-content-32">7.6 Anti-padrões clássicos (resumo rápido)</a><li><a href="#77-mentalidade-correta-isr-como-fronteira-de-tempo-real">7.7 Mentalidade correta: ISR como fronteira de tempo real</a></li></ul><li><a href="#eb-table-content-34">Conclusão – ISR + FreeRTOS como arquitetura, não como detalhe</a></ul></div></div></div></div></div>


<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Em sistemas embarcados modernos, a combinação entre <strong>rotinas de interrupção (ISR – <em>Interrupt Service Routines</em>)</strong> e um <strong>sistema operacional de tempo real (RTOS – <em>Real-Time Operating System</em>)</strong> é praticamente inevitável. Sensores, timers, interfaces de comunicação (UART, SPI, I2C, Ethernet), conversores ADC e eventos externos dependem fortemente de interrupções para garantir baixa latência e previsibilidade. No entanto, quando um RTOS como o FreeRTOS entra em cena, o uso ingênuo de ISRs — comum em sistemas bare-metal — passa a ser uma fonte frequente de bugs, <em>deadlocks</em>, <em>starvation</em> e violações temporais.</p>



<p class="wp-block-paragraph">O principal motivo é conceitual: <strong>uma ISR não é uma task</strong>. Ela não participa do escalonamento, não pode bloquear, não possui pilha dinâmica extensa e não deve executar lógica complexa. O papel da ISR em um sistema com RTOS é <strong>sinalizar eventos ao sistema</strong>, e não processá-los integralmente. O processamento deve ser delegado às <em>tasks</em>, que operam sob o controle do escalonador e respeitam prioridades, tempos de bloqueio e políticas de sincronização.</p>



<p class="wp-block-paragraph">Outro ponto crítico é que o FreeRTOS é projetado para ser <strong>determinístico</strong>, mas isso só se mantém se as ISRs respeitarem as regras do kernel. Uma ISR longa demais ou que chame APIs incorretas pode quebrar garantias fundamentais do sistema, como latência máxima de resposta, justiça no escalonamento e previsibilidade temporal — características essenciais em sistemas industriais, médicos e automotivos.</p>



<p class="wp-block-paragraph">Neste artigo, vamos sair do nível conceitual abstrato e entrar na <strong>prática real de ISR + RTOS</strong>, cobrindo:</p>



<ul class="wp-block-list">
<li>Como o FreeRTOS enxerga uma interrupção</li>



<li>Por que existem APIs específicas “FromISR”</li>



<li>Como sinalizar tasks a partir de ISRs de forma segura</li>



<li>Quando usar semáforos, filas, notificações e event groups</li>



<li>Boas práticas arquiteturais e armadilhas comuns</li>
</ul>



<p class="wp-block-paragraph">O foco será sempre <strong>didático, técnico e aplicável</strong>, com exemplos em C para microcontroladores Cortex-M (como STM32), mantendo o rigor exigido por aplicações profissionais.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/isr-rtos-na-pratica-com-freertos/">ISR + RTOS na Prática com FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1044</post-id>	</item>
		<item>
		<title>Idle Task, Hook Functions e Low Power no FreeRTOS: Guia Completo para Sistemas Embarcados Eficientes</title>
		<link>https://mcu.tec.br/rtos/idle-task-hook-functions-e-low-power-no-freertos-guia-completo-para-sistemas-embarcados-eficientes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=idle-task-hook-functions-e-low-power-no-freertos-guia-completo-para-sistemas-embarcados-eficientes</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 23 Jan 2026 20:33:54 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[FreeRTOS consumo de energia]]></category>
		<category><![CDATA[freeRTOS cortex-m]]></category>
		<category><![CDATA[FreeRTOS power management]]></category>
		<category><![CDATA[FreeRTOS STM32]]></category>
		<category><![CDATA[gerenciamento de energia em RTOS]]></category>
		<category><![CDATA[Idle Hook FreeRTOS]]></category>
		<category><![CDATA[Idle Task FreeRTOS]]></category>
		<category><![CDATA[Low Power FreeRTOS]]></category>
		<category><![CDATA[RTOS low power]]></category>
		<category><![CDATA[sistemas embarcados baixo consumo]]></category>
		<category><![CDATA[Tick Hook FreeRTOS]]></category>
		<category><![CDATA[Tickless Idle FreeRTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1028</guid>

					<description><![CDATA[<p>Neste artigo técnico e didático, exploramos em profundidade como o FreeRTOS gerencia períodos de ociosidade e consumo de energia por meio da Idle Task, das Hook Functions e dos mecanismos de Low Power, incluindo o Tickless Idle. O texto apresenta uma visão arquitetural clara sobre o papel da Idle Task no kernel, explicando por que ela é essencial para a integridade do sistema e quais são as restrições corretas de uso. Em seguida, detalha o funcionamento das Hook Functions, com foco especial na Idle Hook e na Tick Hook, comparando seus contextos de execução, limitações e aplicações práticas. O artigo avança para uma análise completa das estratégias de baixo consumo no FreeRTOS, mostrando como o Tickless Idle permite suspender o tick do sistema e reduzir drasticamente o consumo energético sem perder precisão temporal. São apresentados exemplos de código em C, padrões de implementação para microcontroladores Cortex-M e STM32, além de boas práticas, erros comuns e critérios objetivos para decidir entre abordagens simples e soluções completas de gerenciamento de energia. Este conteúdo é ideal para desenvolvedores de firmware, engenheiros de sistemas embarcados e profissionais que desejam projetar aplicações robustas, previsíveis e energeticamente eficientes com FreeRTOS.</p>
<p>The post <a href="https://mcu.tec.br/rtos/idle-task-hook-functions-e-low-power-no-freertos-guia-completo-para-sistemas-embarcados-eficientes/">Idle Task, Hook Functions e Low Power no FreeRTOS: Guia Completo para Sistemas Embarcados Eficientes</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-hiv2o wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-hiv2o "><div class="eb-toc-container eb-toc-hiv2o  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;Vis\u00e3o Geral: Idle Task, Hook Functions e Low Power no FreeRTOS&quot;,&quot;text&quot;:&quot;Vis\u00e3o Geral: Idle Task, Hook Functions e Low Power no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso.Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso&quot;,&quot;text&quot;:&quot;Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso.Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso&quot;,&quot;link&quot;:&quot;idle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-usoidle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-uso&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Idle Hook (vApplicationIdleHook): extens\u00e3o segura do comportamento da Idle Task&quot;,&quot;text&quot;:&quot;Idle Hook (vApplicationIdleHook): extens\u00e3o segura do comportamento da Idle Task&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Hook Functions no FreeRTOS: Idle Hook vs Tick Hook&quot;,&quot;text&quot;:&quot;Hook Functions no FreeRTOS: Idle Hook vs Tick Hook&quot;,&quot;link&quot;:&quot;hook-functions-no-freertos-idle-hook-vs-tick-hook&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Low Power no FreeRTOS e o conceito de Tickless Idle&quot;,&quot;text&quot;:&quot;Low Power no FreeRTOS e o conceito de Tickless Idle&quot;,&quot;link&quot;:&quot;low-power-no-freertos-e-o-conceito-de-tickless-idle&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Implementa\u00e7\u00e3o pr\u00e1tica de Low Power no FreeRTOS (STM32 e Cortex-M)&quot;,&quot;text&quot;:&quot;Implementa\u00e7\u00e3o pr\u00e1tica de Low Power no FreeRTOS (STM32 e Cortex-M)&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;1. Modelo mental correto: o kernel decide, o port executa&quot;,&quot;text&quot;:&quot;1. Modelo mental correto: o kernel decide, o port executa&quot;,&quot;link&quot;:&quot;1-modelo-mental-correto-o-kernel-decide-o-port-executa&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;2. Exemplo realista: STM32 + FreeRTOS + Sleep Mode&quot;,&quot;text&quot;:&quot;2. Exemplo realista: STM32 + FreeRTOS + Sleep Mode&quot;,&quot;link&quot;:&quot;2-exemplo-realista-stm32-freertos-sleep-mode&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;3. Stop Mode: quando o consumo precisa ser agressivamente reduzido&quot;,&quot;text&quot;:&quot;3. Stop Mode: quando o consumo precisa ser agressivamente reduzido&quot;,&quot;link&quot;:&quot;3-stop-mode-quando-o-consumo-precisa-ser-agressivamente-reduzido&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4. Rela\u00e7\u00e3o entre Idle Hook e Tickless Idle&quot;,&quot;text&quot;:&quot;4. Rela\u00e7\u00e3o entre Idle Hook e Tickless Idle&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5. Erros cl\u00e1ssicos que quebram o Low Power&quot;,&quot;text&quot;:&quot;5. Erros cl\u00e1ssicos que quebram o Low Power&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6. Padr\u00e3o recomendado de arquitetura&quot;,&quot;text&quot;:&quot;6. Padr\u00e3o recomendado de arquitetura&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot; Boas pr\u00e1ticas, checklist e crit\u00e9rios de decis\u00e3o&quot;,&quot;text&quot;:&quot; Boas pr\u00e1ticas, checklist e crit\u00e9rios de decis\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;1. Boas pr\u00e1ticas consolidadas&quot;,&quot;text&quot;:&quot;1. Boas pr\u00e1ticas consolidadas&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;2. Checklist t\u00e9cnico para projetos FreeRTOS&quot;,&quot;text&quot;:&quot;2. Checklist t\u00e9cnico para projetos FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;3. Crit\u00e9rios de decis\u00e3o: Idle Hook vs Tickless Idle&quot;,&quot;text&quot;:&quot;3. Crit\u00e9rios de decis\u00e3o: Idle Hook vs Tickless Idle&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4. S\u00edntese arquitetural&quot;,&quot;text&quot;:&quot;4. S\u00edntese arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Vis\u00e3o Geral: Idle Task, Hook Functions e Low Power no FreeRTOS&quot;,&quot;value&quot;:&quot;vis\u00e3o-geral-idle-task-hook-functions-e-low-power-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso.Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso&quot;,&quot;value&quot;:&quot;idle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-usoidle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-uso&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Idle Hook (vApplicationIdleHook): extens\u00e3o segura do comportamento da Idle Task&quot;,&quot;value&quot;:&quot;idle-hook-vapplicationidlehook-extens\u00e3o-segura-do-comportamento-da-idle-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Hook Functions no FreeRTOS: Idle Hook vs Tick Hook&quot;,&quot;value&quot;:&quot;hook-functions-no-freertos-idle-hook-vs-tick-hook&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Low Power no FreeRTOS e o conceito de Tickless Idle&quot;,&quot;value&quot;:&quot;low-power-no-freertos-e-o-conceito-de-tickless-idle&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implementa\u00e7\u00e3o pr\u00e1tica de Low Power no FreeRTOS (STM32 e Cortex-M)&quot;,&quot;value&quot;:&quot;implementa\u00e7\u00e3o-pr\u00e1tica-de-low-power-no-freertos-stm32-e-cortex-m&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1. Modelo mental correto: o kernel decide, o port executa&quot;,&quot;value&quot;:&quot;1-modelo-mental-correto-o-kernel-decide-o-port-executa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2. Exemplo realista: STM32 + FreeRTOS + Sleep Mode&quot;,&quot;value&quot;:&quot;2-exemplo-realista-stm32-freertos-sleep-mode&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3. Stop Mode: quando o consumo precisa ser agressivamente reduzido&quot;,&quot;value&quot;:&quot;3-stop-mode-quando-o-consumo-precisa-ser-agressivamente-reduzido&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4. Rela\u00e7\u00e3o entre Idle Hook e Tickless Idle&quot;,&quot;value&quot;:&quot;4-rela\u00e7\u00e3o-entre-idle-hook-e-tickless-idle&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5. Erros cl\u00e1ssicos que quebram o Low Power&quot;,&quot;value&quot;:&quot;5-erros-cl\u00e1ssicos-que-quebram-o-low-power&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6. Padr\u00e3o recomendado de arquitetura&quot;,&quot;value&quot;:&quot;6-padr\u00e3o-recomendado-de-arquitetura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot; Boas pr\u00e1ticas, checklist e crit\u00e9rios de decis\u00e3o&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-checklist-e-crit\u00e9rios-de-decis\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1. Boas pr\u00e1ticas consolidadas&quot;,&quot;value&quot;:&quot;1-boas-pr\u00e1ticas-consolidadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2. Checklist t\u00e9cnico para projetos FreeRTOS&quot;,&quot;value&quot;:&quot;2-checklist-t\u00e9cnico-para-projetos-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3. Crit\u00e9rios de decis\u00e3o: Idle Hook vs Tickless Idle&quot;,&quot;value&quot;:&quot;3-crit\u00e9rios-de-decis\u00e3o-idle-hook-vs-tickless-idle&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4. S\u00edntese arquitetural&quot;,&quot;value&quot;:&quot;4-s\u00edntese-arquitetural&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Visão Geral: Idle Task, Hook Functions e Low Power no FreeRTOS</a><li><a href="#idle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-usoidle-task-no-freertos-papel-ciclo-de-vida-e-regras-de-uso">Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso.Idle Task no FreeRTOS: papel, ciclo de vida e regras de uso</a><li><a href="#eb-table-content-2">Idle Hook (vApplicationIdleHook): extensão segura do comportamento da Idle Task</a><li><a href="#hook-functions-no-freertos-idle-hook-vs-tick-hook">Hook Functions no FreeRTOS: Idle Hook vs Tick Hook</a><li><a href="#low-power-no-freertos-e-o-conceito-de-tickless-idle">Low Power no FreeRTOS e o conceito de Tickless Idle</a><ul class="eb-toc__list"><li><a href="#eb-table-content-5">Implementação prática de Low Power no FreeRTOS (STM32 e Cortex-M)</a><ul class="eb-toc__list"><li><a href="#1-modelo-mental-correto-o-kernel-decide-o-port-executa">1. Modelo mental correto: o kernel decide, o port executa</a><li><a href="#2-exemplo-realista-stm32-freertos-sleep-mode">2. Exemplo realista: STM32 + FreeRTOS + Sleep Mode</a><li><a href="#3-stop-mode-quando-o-consumo-precisa-ser-agressivamente-reduzido">3. Stop Mode: quando o consumo precisa ser agressivamente reduzido</a><li><a href="#eb-table-content-9">4. Relação entre Idle Hook e Tickless Idle</a><li><a href="#eb-table-content-10">5. Erros clássicos que quebram o Low Power</a><li><a href="#eb-table-content-11">6. Padrão recomendado de arquitetura</a></li></ul></li></ul><li><a href="#eb-table-content-12"> Boas práticas, checklist e critérios de decisão</a><ul class="eb-toc__list"><li><a href="#eb-table-content-13">1. Boas práticas consolidadas</a><li><a href="#eb-table-content-14">2. Checklist técnico para projetos FreeRTOS</a><li><a href="#eb-table-content-15">3. Critérios de decisão: Idle Hook vs Tickless Idle</a><li><a href="#eb-table-content-16">4. Síntese arquitetural</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading"><strong>Visão Geral: Idle Task, Hook Functions e Low Power no FreeRTOS</strong></h2>



<p class="wp-block-paragraph">Nesta seção introdutória vamos estabelecer o <strong>contexto conceitual</strong> que conecta três elementos fundamentais do FreeRTOS: a <strong>Idle Task</strong>, as <strong>Hook Functions</strong> associadas a ela e os <strong>mecanismos de baixo consumo de energia (Low Power)</strong>. Esses três tópicos formam um <strong>tripé arquitetural</strong> que influencia diretamente o desempenho, a previsibilidade temporal e a eficiência energética de sistemas embarcados baseados em RTOS, especialmente em microcontroladores Cortex-M, RISC-V e similares.</p>



<p class="wp-block-paragraph">No FreeRTOS, a <strong>Idle Task</strong> é uma tarefa criada automaticamente pelo kernel, com a <strong>menor prioridade possível</strong>. Sua função primária é simples, porém crítica: garantir que o escalonador sempre tenha algo para executar quando <strong>nenhuma outra tarefa pronta</strong> está disponível. Diferente de uma tarefa de aplicação, a Idle Task não representa uma funcionalidade do sistema, mas sim um <strong>estado operacional do kernel</strong>, sendo o ponto natural onde o sistema pode executar atividades de manutenção, limpeza de recursos e, principalmente, <strong>entrar em modos de baixo consumo</strong>.</p>



<p class="wp-block-paragraph">É exatamente nesse ponto que entram as <strong>Hook Functions</strong>. Hooks são funções de callback definidas pelo usuário e chamadas pelo kernel em momentos bem específicos de sua execução. No contexto deste artigo, duas hooks são centrais:</p>



<ul class="wp-block-list">
<li><strong>Idle Hook (<code>vApplicationIdleHook</code>)</strong>, chamada repetidamente sempre que a Idle Task está executando.</li>



<li><strong>Tick Hook (<code>vApplicationTickHook</code>)</strong>, chamada a cada interrupção de tick do sistema.</li>
</ul>



<p class="wp-block-paragraph">Essas funções permitem ao desenvolvedor <strong>estender o comportamento do kernel sem modificá-lo</strong>, inserindo lógica customizada como monitoramento, estatísticas, watchdogs e — de forma muito comum — <strong>estratégias de economia de energia</strong>.</p>



<p class="wp-block-paragraph">A integração com <strong>Low Power</strong> ocorre quando o desenvolvedor percebe que a Idle Task representa, conceitualmente, o momento em que o sistema <strong>não tem trabalho útil a fazer</strong>. Em microcontroladores modernos, isso é um convite direto para colocar o núcleo em estados como <em>Sleep</em>, <em>Stop</em> ou até <em>Standby</em>. O FreeRTOS fornece suporte explícito a isso por meio do recurso conhecido como <strong>Tickless Idle</strong>, onde o kernel suspende o timer de tick periódico e permite que o processador durma por intervalos longos, acordando apenas quando necessário.</p>



<p class="wp-block-paragraph">Portanto, entender Idle Task, Hooks e Low Power não é apenas conhecer APIs isoladas, mas compreender <strong>como o FreeRTOS modela o tempo ocioso</strong> do sistema e como esse tempo pode ser convertido em <strong>eficiência energética real</strong>, sem sacrificar determinismo nem confiabilidade. Nas próximas seções, vamos desmontar cada um desses conceitos, começando pelo funcionamento interno da Idle Task, passando pelas hooks associadas e chegando à implementação prática de modos de baixo consumo com exemplos completos em C.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/idle-task-hook-functions-e-low-power-no-freertos-guia-completo-para-sistemas-embarcados-eficientes/">Idle Task, Hook Functions e Low Power no FreeRTOS: Guia Completo para Sistemas Embarcados Eficientes</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1028</post-id>	</item>
		<item>
		<title>Dimensionamento de Pilha (Stack) e Heap no FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/dimensionamento-de-pilha-stack-e-heap-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dimensionamento-de-pilha-stack-e-heap-no-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 16 Jan 2026 19:52:45 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[ARM Cortex-M RTOS]]></category>
		<category><![CDATA[dimensionamento de memória RTOS]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[gerenciamento de memória embarcado]]></category>
		<category><![CDATA[heap no FreeRTOS]]></category>
		<category><![CDATA[heap_4 FreeRTOS]]></category>
		<category><![CDATA[heap_5 FreeRTOS]]></category>
		<category><![CDATA[stack no FreeRTOS]]></category>
		<category><![CDATA[stack overflow FreeRTOS]]></category>
		<category><![CDATA[TCB FreeRTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1021</guid>

					<description><![CDATA[<p>Aprenda como dimensionar corretamente stack e heap no FreeRTOS com explicações detalhadas sobre TCB, heap e stack, cálculos práticos, fórmulas, exemplos em C e boas práticas profissionais. Este guia técnico aborda erros comuns, sintomas em campo e estratégias robustas para evitar falhas, fragmentação de memória e resets inesperados em sistemas embarcados baseados em RTOS, especialmente em microcontroladores ARM Cortex-M.</p>
<p>The post <a href="https://mcu.tec.br/rtos/dimensionamento-de-pilha-stack-e-heap-no-freertos/">Dimensionamento de Pilha (Stack) e Heap no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-g038z wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-g038z "><div class="eb-toc-container eb-toc-g038z  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Por que dimensionar corretamente Stack e Heap em sistemas com FreeRTOS&quot;,&quot;text&quot;:&quot;Por que dimensionar corretamente Stack e Heap em sistemas com FreeRTOS&quot;,&quot;link&quot;:&quot;por-que-dimensionar-corretamente-stack-e-heap-em-sistemas-com-freertos&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Modelo de Mem\u00f3ria em Sistemas com FreeRTOS: CTB, Heap e Stack&quot;,&quot;text&quot;:&quot;Modelo de Mem\u00f3ria em Sistemas com FreeRTOS: CTB, Heap e Stack&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 CTB (Control Block \/ TCB \u2013 Task Control Block)&quot;,&quot;text&quot;:&quot;2.1 CTB (Control Block \/ TCB \u2013 Task Control Block)&quot;,&quot;link&quot;:&quot;21-ctb-control-block-tcb-task-control-block&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 Heap no FreeRTOS&quot;,&quot;text&quot;:&quot;2.2 Heap no FreeRTOS&quot;,&quot;link&quot;:&quot;22-heap-no-freertos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 Stack no FreeRTOS&quot;,&quot;text&quot;:&quot;2.3 Stack no FreeRTOS&quot;,&quot;link&quot;:&quot;23-stack-no-freertos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 Rela\u00e7\u00e3o entre Heap, TCB e Stack&quot;,&quot;text&quot;:&quot;2.4 Rela\u00e7\u00e3o entre Heap, TCB e Stack&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Stack no FreeRTOS: Funcionamento Interno, Cortex-M e Impacto das Interrup\u00e7\u00f5es&quot;,&quot;text&quot;:&quot;Stack no FreeRTOS: Funcionamento Interno, Cortex-M e Impacto das Interrup\u00e7\u00f5es&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 O que realmente vai para a stack de uma task&quot;,&quot;text&quot;:&quot;3.1 O que realmente vai para a stack de uma task&quot;,&quot;link&quot;:&quot;31-o-que-realmente-vai-para-a-stack-de-uma-task&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Empilhamento autom\u00e1tico no Cortex-M (hardware stacking)&quot;,&quot;text&quot;:&quot;3.2 Empilhamento autom\u00e1tico no Cortex-M (hardware stacking)&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Stack da Task vs Stack da Interrup\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;3.3 Stack da Task vs Stack da Interrup\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 F\u00f3rmula pr\u00e1tica para estimativa inicial de stack&quot;,&quot;text&quot;:&quot;3.4 F\u00f3rmula pr\u00e1tica para estimativa inicial de stack&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Erros cl\u00e1ssicos de dimensionamento de stack&quot;,&quot;text&quot;:&quot;3.5 Erros cl\u00e1ssicos de dimensionamento de stack&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Detec\u00e7\u00e3o e medi\u00e7\u00e3o de stack no FreeRTOS&quot;,&quot;text&quot;:&quot;3.6 Detec\u00e7\u00e3o e medi\u00e7\u00e3o de stack no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Heap no FreeRTOS: Modelos, Fragmenta\u00e7\u00e3o e Impacto no Sistema&quot;,&quot;text&quot;:&quot;Heap no FreeRTOS: Modelos, Fragmenta\u00e7\u00e3o e Impacto no Sistema&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 O que realmente consome heap no FreeRTOS&quot;,&quot;text&quot;:&quot;4.1 O que realmente consome heap no FreeRTOS&quot;,&quot;link&quot;:&quot;41-o-que-realmente-consome-heap-no-freertos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Os cinco modelos de heap do FreeRTOS&quot;,&quot;text&quot;:&quot;4.2 Os cinco modelos de heap do FreeRTOS&quot;,&quot;link&quot;:&quot;42-os-cinco-modelos-de-heap-do-freertos&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;heap_1&quot;,&quot;text&quot;:&quot;heap_1&quot;,&quot;link&quot;:&quot;heap_1&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;heap_2&quot;,&quot;text&quot;:&quot;heap_2&quot;,&quot;link&quot;:&quot;heap_2&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;heap_3&quot;,&quot;text&quot;:&quot;heap_3&quot;,&quot;link&quot;:&quot;heap_3&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;heap_4 (mais usado na pr\u00e1tica)&quot;,&quot;text&quot;:&quot;heap_4 (mais usado na pr\u00e1tica)&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;heap_5&quot;,&quot;text&quot;:&quot;heap_5&quot;,&quot;link&quot;:&quot;heap_5&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Estrutura interna do heap_4&quot;,&quot;text&quot;:&quot;4.3 Estrutura interna do heap_4&quot;,&quot;link&quot;:&quot;43-estrutura-interna-do-heap_4&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 C\u00e1lculo do heap necess\u00e1rio (estimativa inicial)&quot;,&quot;text&quot;:&quot;4.4 C\u00e1lculo do heap necess\u00e1rio (estimativa inicial)&quot;,&quot;link&quot;:&quot;eb-table-content-22&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Fragmenta\u00e7\u00e3o: o inimigo invis\u00edvel&quot;,&quot;text&quot;:&quot;4.5 Fragmenta\u00e7\u00e3o: o inimigo invis\u00edvel&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.6 Heap est\u00e1tico vs heap din\u00e2mico&quot;,&quot;text&quot;:&quot;4.6 Heap est\u00e1tico vs heap din\u00e2mico&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Estrat\u00e9gia Profissional de Dimensionamento: M\u00e9todo Passo a Passo&quot;,&quot;text&quot;:&quot;Estrat\u00e9gia Profissional de Dimensionamento: M\u00e9todo Passo a Passo&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Passo 1 \u2014 Mapear todas as entidades que consomem mem\u00f3ria&quot;,&quot;text&quot;:&quot;5.1 Passo 1 \u2014 Mapear todas as entidades que consomem mem\u00f3ria&quot;,&quot;link&quot;:&quot;eb-table-content-26&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Passo 2 \u2014 Dimensionar stack individualmente (n\u00e3o por m\u00e9dia)&quot;,&quot;text&quot;:&quot;5.2 Passo 2 \u2014 Dimensionar stack individualmente (n\u00e3o por m\u00e9dia)&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Passo 3 \u2014 Converter tudo para palavras (n\u00e3o bytes)&quot;,&quot;text&quot;:&quot;5.3 Passo 3 \u2014 Converter tudo para palavras (n\u00e3o bytes)&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Passo 4 \u2014 Calcular o heap total&quot;,&quot;text&quot;:&quot;5.4 Passo 4 \u2014 Calcular o heap total&quot;,&quot;link&quot;:&quot;54-passo-4-calcular-o-heap-total&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Passo 5 \u2014 Validar em tempo de execu\u00e7\u00e3o (watermark)&quot;,&quot;text&quot;:&quot;5.5 Passo 5 \u2014 Validar em tempo de execu\u00e7\u00e3o (watermark)&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Passo 6 \u2014 Habilitar prote\u00e7\u00f5es obrigat\u00f3rias&quot;,&quot;text&quot;:&quot;5.6 Passo 6 \u2014 Habilitar prote\u00e7\u00f5es obrigat\u00f3rias&quot;,&quot;link&quot;:&quot;eb-table-content-31&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.7 Passo 7 \u2014 Preferir cria\u00e7\u00e3o est\u00e1tica quando poss\u00edvel&quot;,&quot;text&quot;:&quot;5.7 Passo 7 \u2014 Preferir cria\u00e7\u00e3o est\u00e1tica quando poss\u00edvel&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Erros Comuns, Sintomas em Campo e Boas Pr\u00e1ticas Consolidadas&quot;,&quot;text&quot;:&quot;Erros Comuns, Sintomas em Campo e Boas Pr\u00e1ticas Consolidadas&quot;,&quot;link&quot;:&quot;eb-table-content-33&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 Sintomas t\u00edpicos de erro de stack&quot;,&quot;text&quot;:&quot;6.1 Sintomas t\u00edpicos de erro de stack&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Sintomas t\u00edpicos de erro de heap&quot;,&quot;text&quot;:&quot;6.2 Sintomas t\u00edpicos de erro de heap&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Erros conceituais mais comuns&quot;,&quot;text&quot;:&quot;6.3 Erros conceituais mais comuns&quot;,&quot;link&quot;:&quot;63-erros-conceituais-mais-comuns&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 Boas pr\u00e1ticas consolidadas em projetos profissionais&quot;,&quot;text&quot;:&quot;6.4 Boas pr\u00e1ticas consolidadas em projetos profissionais&quot;,&quot;link&quot;:&quot;eb-table-content-37&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.5 Conclus\u00e3o t\u00e9cnica&quot;,&quot;text&quot;:&quot;6.5 Conclus\u00e3o t\u00e9cnica&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Por que dimensionar corretamente Stack e Heap em sistemas com FreeRTOS&quot;,&quot;value&quot;:&quot;por-que-dimensionar-corretamente-stack-e-heap-em-sistemas-com-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo de Mem\u00f3ria em Sistemas com FreeRTOS: CTB, Heap e Stack&quot;,&quot;value&quot;:&quot;modelo-de-mem\u00f3ria-em-sistemas-com-freertos-ctb-heap-e-stack&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 CTB (Control Block \/ TCB \u2013 Task Control Block)&quot;,&quot;value&quot;:&quot;21-ctb-control-block-tcb-task-control-block&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 Heap no FreeRTOS&quot;,&quot;value&quot;:&quot;22-heap-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 Stack no FreeRTOS&quot;,&quot;value&quot;:&quot;23-stack-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 Rela\u00e7\u00e3o entre Heap, TCB e Stack&quot;,&quot;value&quot;:&quot;24-rela\u00e7\u00e3o-entre-heap-tcb-e-stack&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stack no FreeRTOS: Funcionamento Interno, Cortex-M e Impacto das Interrup\u00e7\u00f5es&quot;,&quot;value&quot;:&quot;stack-no-freertos-funcionamento-interno-cortex-m-e-impacto-das-interrup\u00e7\u00f5es&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 O que realmente vai para a stack de uma task&quot;,&quot;value&quot;:&quot;31-o-que-realmente-vai-para-a-stack-de-uma-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Empilhamento autom\u00e1tico no Cortex-M (hardware stacking)&quot;,&quot;value&quot;:&quot;32-empilhamento-autom\u00e1tico-no-cortex-m-hardware-stacking&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Stack da Task vs Stack da Interrup\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;33-stack-da-task-vs-stack-da-interrup\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 F\u00f3rmula pr\u00e1tica para estimativa inicial de stack&quot;,&quot;value&quot;:&quot;34-f\u00f3rmula-pr\u00e1tica-para-estimativa-inicial-de-stack&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Erros cl\u00e1ssicos de dimensionamento de stack&quot;,&quot;value&quot;:&quot;35-erros-cl\u00e1ssicos-de-dimensionamento-de-stack&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Detec\u00e7\u00e3o e medi\u00e7\u00e3o de stack no FreeRTOS&quot;,&quot;value&quot;:&quot;36-detec\u00e7\u00e3o-e-medi\u00e7\u00e3o-de-stack-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Heap no FreeRTOS: Modelos, Fragmenta\u00e7\u00e3o e Impacto no Sistema&quot;,&quot;value&quot;:&quot;heap-no-freertos-modelos-fragmenta\u00e7\u00e3o-e-impacto-no-sistema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 O que realmente consome heap no FreeRTOS&quot;,&quot;value&quot;:&quot;41-o-que-realmente-consome-heap-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Os cinco modelos de heap do FreeRTOS&quot;,&quot;value&quot;:&quot;42-os-cinco-modelos-de-heap-do-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;heap_1&quot;,&quot;value&quot;:&quot;heap_1&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;heap_2&quot;,&quot;value&quot;:&quot;heap_2&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;heap_3&quot;,&quot;value&quot;:&quot;heap_3&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;heap_4 (mais usado na pr\u00e1tica)&quot;,&quot;value&quot;:&quot;heap_4-mais-usado-na-pr\u00e1tica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;heap_5&quot;,&quot;value&quot;:&quot;heap_5&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Estrutura interna do heap_4&quot;,&quot;value&quot;:&quot;43-estrutura-interna-do-heap_4&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 C\u00e1lculo do heap necess\u00e1rio (estimativa inicial)&quot;,&quot;value&quot;:&quot;44-c\u00e1lculo-do-heap-necess\u00e1rio-estimativa-inicial&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Fragmenta\u00e7\u00e3o: o inimigo invis\u00edvel&quot;,&quot;value&quot;:&quot;45-fragmenta\u00e7\u00e3o-o-inimigo-invis\u00edvel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.6 Heap est\u00e1tico vs heap din\u00e2mico&quot;,&quot;value&quot;:&quot;46-heap-est\u00e1tico-vs-heap-din\u00e2mico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrat\u00e9gia Profissional de Dimensionamento: M\u00e9todo Passo a Passo&quot;,&quot;value&quot;:&quot;estrat\u00e9gia-profissional-de-dimensionamento-m\u00e9todo-passo-a-passo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Passo 1 \u2014 Mapear todas as entidades que consomem mem\u00f3ria&quot;,&quot;value&quot;:&quot;51-passo-1-mapear-todas-as-entidades-que-consomem-mem\u00f3ria&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Passo 2 \u2014 Dimensionar stack individualmente (n\u00e3o por m\u00e9dia)&quot;,&quot;value&quot;:&quot;52-passo-2-dimensionar-stack-individualmente-n\u00e3o-por-m\u00e9dia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Passo 3 \u2014 Converter tudo para palavras (n\u00e3o bytes)&quot;,&quot;value&quot;:&quot;53-passo-3-converter-tudo-para-palavras-n\u00e3o-bytes&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Passo 4 \u2014 Calcular o heap total&quot;,&quot;value&quot;:&quot;54-passo-4-calcular-o-heap-total&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Passo 5 \u2014 Validar em tempo de execu\u00e7\u00e3o (watermark)&quot;,&quot;value&quot;:&quot;55-passo-5-validar-em-tempo-de-execu\u00e7\u00e3o-watermark&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Passo 6 \u2014 Habilitar prote\u00e7\u00f5es obrigat\u00f3rias&quot;,&quot;value&quot;:&quot;56-passo-6-habilitar-prote\u00e7\u00f5es-obrigat\u00f3rias&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7 Passo 7 \u2014 Preferir cria\u00e7\u00e3o est\u00e1tica quando poss\u00edvel&quot;,&quot;value&quot;:&quot;57-passo-7-preferir-cria\u00e7\u00e3o-est\u00e1tica-quando-poss\u00edvel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erros Comuns, Sintomas em Campo e Boas Pr\u00e1ticas Consolidadas&quot;,&quot;value&quot;:&quot;erros-comuns-sintomas-em-campo-e-boas-pr\u00e1ticas-consolidadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 Sintomas t\u00edpicos de erro de stack&quot;,&quot;value&quot;:&quot;61-sintomas-t\u00edpicos-de-erro-de-stack&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Sintomas t\u00edpicos de erro de heap&quot;,&quot;value&quot;:&quot;62-sintomas-t\u00edpicos-de-erro-de-heap&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Erros conceituais mais comuns&quot;,&quot;value&quot;:&quot;63-erros-conceituais-mais-comuns&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 Boas pr\u00e1ticas consolidadas em projetos profissionais&quot;,&quot;value&quot;:&quot;64-boas-pr\u00e1ticas-consolidadas-em-projetos-profissionais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.5 Conclus\u00e3o t\u00e9cnica&quot;,&quot;value&quot;:&quot;65-conclus\u00e3o-t\u00e9cnica&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#por-que-dimensionar-corretamente-stack-e-heap-em-sistemas-com-freertos">Por que dimensionar corretamente Stack e Heap em sistemas com FreeRTOS</a><li><a href="#eb-table-content-1">Modelo de Memória em Sistemas com FreeRTOS: CTB, Heap e Stack</a><ul class="eb-toc__list"><li><a href="#21-ctb-control-block-tcb-task-control-block">2.1 CTB (Control Block / TCB – Task Control Block)</a><li><a href="#22-heap-no-freertos">2.2 Heap no FreeRTOS</a><li><a href="#23-stack-no-freertos">2.3 Stack no FreeRTOS</a><li><a href="#eb-table-content-5">2.4 Relação entre Heap, TCB e Stack</a></li></ul><li><a href="#eb-table-content-6">Stack no FreeRTOS: Funcionamento Interno, Cortex-M e Impacto das Interrupções</a><ul class="eb-toc__list"><li><a href="#31-o-que-realmente-vai-para-a-stack-de-uma-task">3.1 O que realmente vai para a stack de uma task</a><li><a href="#eb-table-content-8">3.2 Empilhamento automático no Cortex-M (hardware stacking)</a><li><a href="#eb-table-content-9">3.3 Stack da Task vs Stack da Interrupção</a><li><a href="#eb-table-content-10">3.4 Fórmula prática para estimativa inicial de stack</a><li><a href="#eb-table-content-11">3.5 Erros clássicos de dimensionamento de stack</a><li><a href="#eb-table-content-12">3.6 Detecção e medição de stack no FreeRTOS</a></li></ul><li><a href="#eb-table-content-13">Heap no FreeRTOS: Modelos, Fragmentação e Impacto no Sistema</a><ul class="eb-toc__list"><li><a href="#41-o-que-realmente-consome-heap-no-freertos">4.1 O que realmente consome heap no FreeRTOS</a><li><a href="#42-os-cinco-modelos-de-heap-do-freertos">4.2 Os cinco modelos de heap do FreeRTOS</a><ul class="eb-toc__list"><li><a href="#heap_1">heap_1</a><li><a href="#heap_2">heap_2</a><li><a href="#heap_3">heap_3</a><li><a href="#eb-table-content-19">heap_4 (mais usado na prática)</a><li><a href="#heap_5">heap_5</a></li></ul><li><a href="#43-estrutura-interna-do-heap_4">4.3 Estrutura interna do heap_4</a><li><a href="#eb-table-content-22">4.4 Cálculo do heap necessário (estimativa inicial)</a><li><a href="#eb-table-content-23">4.5 Fragmentação: o inimigo invisível</a><li><a href="#eb-table-content-24">4.6 Heap estático vs heap dinâmico</a></li></ul><li><a href="#eb-table-content-25">Estratégia Profissional de Dimensionamento: Método Passo a Passo</a><ul class="eb-toc__list"><li><a href="#eb-table-content-26">5.1 Passo 1 — Mapear todas as entidades que consomem memória</a><li><a href="#eb-table-content-27">5.2 Passo 2 — Dimensionar stack individualmente (não por média)</a><li><a href="#eb-table-content-28">5.3 Passo 3 — Converter tudo para palavras (não bytes)</a><li><a href="#54-passo-4-calcular-o-heap-total">5.4 Passo 4 — Calcular o heap total</a><li><a href="#eb-table-content-30">5.5 Passo 5 — Validar em tempo de execução (watermark)</a><li><a href="#eb-table-content-31">5.6 Passo 6 — Habilitar proteções obrigatórias</a><li><a href="#eb-table-content-32">5.7 Passo 7 — Preferir criação estática quando possível</a></li></ul><li><a href="#eb-table-content-33">Erros Comuns, Sintomas em Campo e Boas Práticas Consolidadas</a><ul class="eb-toc__list"><li><a href="#eb-table-content-34">6.1 Sintomas típicos de erro de stack</a><li><a href="#eb-table-content-35">6.2 Sintomas típicos de erro de heap</a><li><a href="#63-erros-conceituais-mais-comuns">6.3 Erros conceituais mais comuns</a><li><a href="#eb-table-content-37">6.4 Boas práticas consolidadas em projetos profissionais</a><li><a href="#eb-table-content-38">6.5 Conclusão técnica</a></li></ul></ul></div></div></div></div></div>


<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Por que dimensionar corretamente Stack e Heap em sistemas com FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Em sistemas embarcados baseados em RTOS, especialmente no FreeRTOS, o <strong>dimensionamento correto de memória</strong> não é apenas uma questão de otimização, mas de <strong>confiabilidade, previsibilidade temporal e segurança operacional</strong>. Diferente de aplicações desktop, onde há abundância de memória virtual, em microcontroladores lidamos com <strong>SRAM limitada</strong>, geralmente compartilhada entre <strong>heap, stacks das tasks, buffers de drivers, pilha de interrupções e dados globais</strong>.</p>



<p class="wp-block-paragraph">O FreeRTOS introduz um modelo explícito de gerenciamento de memória, separando claramente <strong>Heap do sistema</strong> e <strong>Stack de cada tarefa (Task Stack)</strong>. Essa separação permite maior controle, porém exige do desenvolvedor uma postura ativa: <strong>dimensionar mal significa falhas intermitentes, corrupção silenciosa de memória e resets imprevisíveis</strong>, muitas vezes difíceis de depurar. Em projetos com lwIP, USB, arquivos FAT ou criptografia, esses riscos aumentam drasticamente.</p>



<p class="wp-block-paragraph">Outro ponto crítico é que <strong>erros de stack e heap raramente se manifestam imediatamente</strong>. Um stack subdimensionado pode funcionar por horas ou dias até que uma função mais profunda, uma interrupção específica ou uma condição rara cause overflow. Já o heap mal dimensionado pode fragmentar ou simplesmente falhar ao criar uma task, mutex ou buffer, retornando erros difíceis de rastrear se não houver instrumentação adequada.</p>



<p class="wp-block-paragraph">Por isso, entender <strong>o que é Stack, o que é Heap, como o FreeRTOS os utiliza, como medi-los, como calcular margens seguras e como validar em tempo de execução</strong> é uma competência fundamental para qualquer engenheiro que desenvolva firmware profissional. Este artigo aborda esses pontos de forma sistemática, com foco prático em microcontroladores ARM Cortex-M, mas aplicável a qualquer arquitetura suportada pelo FreeRTOS.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/dimensionamento-de-pilha-stack-e-heap-no-freertos/">Dimensionamento de Pilha (Stack) e Heap no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1021</post-id>	</item>
	</channel>
</rss>
