<?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>Multithreads e Multicore - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/categorias/multithreads-e-multicore/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Thu, 02 Jan 2025 21:46:23 +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>Multithreads e Multicore - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Introdução ao FreeRTOS no ESP32: Controle Multicore e Recursos Avançados</title>
		<link>https://mcu.tec.br/multithreads-e-multicore/introducao-ao-freertos-no-esp32-controle-multicore-e-recursos-avancados/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducao-ao-freertos-no-esp32-controle-multicore-e-recursos-avancados</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 02 Jan 2025 21:28:15 +0000</pubDate>
				<category><![CDATA[Multithreads e Multicore]]></category>
		<category><![CDATA[atomic]]></category>
		<category><![CDATA[C11]]></category>
		<category><![CDATA[condições de corrida]]></category>
		<category><![CDATA[controle exclusivo.]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[funções críticas]]></category>
		<category><![CDATA[grupos de eventos]]></category>
		<category><![CDATA[multicore]]></category>
		<category><![CDATA[multitarefa]]></category>
		<category><![CDATA[mutexes]]></category>
		<category><![CDATA[portENTER_CRITICAL]]></category>
		<category><![CDATA[portEXIT_CRITICAL]]></category>
		<category><![CDATA[semáforos]]></category>
		<category><![CDATA[sincronização]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[vPortCPUInitializeMutex]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=46</guid>

					<description><![CDATA[<p>Este artigo explora o uso avançado do FreeRTOS no ESP32 para sistemas multicore, abordando funções críticas como vPortCPUInitializeMutex, portENTER_CRITICAL e portEXIT_CRITICAL. Ele compara essas ferramentas com a diretiva atomic do C e apresenta outros métodos de sincronização, como semáforos, mutexes e grupos de eventos, destacando práticas recomendadas para garantir desempenho, confiabilidade e segurança em projetos embarcados.</p>
<p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/introducao-ao-freertos-no-esp32-controle-multicore-e-recursos-avancados/">Introdução ao FreeRTOS no ESP32: Controle Multicore e Recursos Avançados</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">O ESP32 é um microcontrolador poderoso com suporte a dois núcleos, permitindo que tarefas sejam distribuídas de maneira eficiente. Para aproveitar ao máximo esse recurso, o uso do FreeRTOS é essencial. O FreeRTOS é um sistema operacional de tempo real amplamente utilizado, que oferece mecanismos para gerenciar tarefas, recursos e sincronização.</p>



<p class="wp-block-paragraph">Neste artigo, exploraremos como o FreeRTOS interage com o ESP32 no contexto multicore, com foco nas funções avançadas como <code>vPortCPUInitializeMutex</code>, <code>portENTER_CRITICAL</code> e <code>portEXIT_CRITICAL</code>. Também faremos uma comparação com a diretiva <code>atomic</code> do C e apresentaremos outros métodos de gerenciamento de recursos e sincronização, como semáforos e mutexes, para ilustrar as melhores práticas e implicações de uso.</p>



<p class="wp-block-paragraph">Nosso objetivo é explicar cada recurso de forma clara e detalhada, com exemplos práticos que demonstram como implementar esses mecanismos no ESP32. Ao final, você terá uma visão completa das opções disponíveis e entenderá como escolher a abordagem ideal para o seu projeto.</p>



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



<h2 class="wp-block-heading">Entendendo as Funções de Controle Crítico no FreeRTOS</h2>



<p class="wp-block-paragraph">Ao trabalhar com sistemas multicore, como o ESP32, é fundamental garantir que determinados trechos de código sejam executados de forma atômica, ou seja, sem interrupções e sem acesso simultâneo por outro núcleo ou tarefa. O FreeRTOS fornece diversas ferramentas para isso, e nesta seção abordaremos três delas: <code>vPortCPUInitializeMutex</code>, <code>portENTER_CRITICAL</code> e <code>portEXIT_CRITICAL</code>.</p>



<h3 class="wp-block-heading">vPortCPUInitializeMutex</h3>



<p class="wp-block-paragraph">A função <code>vPortCPUInitializeMutex</code> é utilizada para inicializar mutexes que podem ser acessados de forma segura entre múltiplos núcleos. Essa função é essencial para garantir que um recurso seja utilizado por apenas uma tarefa de cada vez, independentemente do núcleo em execução.</p>



<h4 class="wp-block-heading">Exemplo de uso:</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" data-code="#include &quot;freertos/FreeRTOS.h&quot;&lt;br&gt;#include &quot;freertos/task.h&quot;
#include &quot;freertos/semphr.h&quot;

portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;

void task1(void *pvParameters) {
    while (true) {
            portENTER_CRITICAL(&amp;myMutex);     // Entra na seção crítica
            printf(&quot;Tarefa 1 está executando em núcleo %d\n&quot;, xPortGetCoreID());
            portEXIT_CRITICAL(&amp;myMutex);      // Sai da seção crítica
            vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

void app_main() {
    vPortCPUInitializeMutex(&amp;myMutex); // Inicializa o mutex para controle multicore
    
    xTaskCreatePinnedToCore(task1, &quot;Task1&quot;, 2048, NULL, 1, NULL, 0);
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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/FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">br</span><span style="color: #81A1C1">&gt;</span><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/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">freertos/semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">portMUX_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">myMutex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMUX_INITIALIZER_UNLOCKED</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">task1</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">portENTER_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">myMutex</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #616E88">// Entra na seção crítica</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa 1 está executando em núcleo %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xPortGetCoreID</span><span style="color: #D8DEE9FF">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">portEXIT_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">myMutex</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">      </span><span style="color: #616E88">// Sai da seção crítica</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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_main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vPortCPUInitializeMutex</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">myMutex</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Inicializa o mutex para controle multicore</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreatePinnedToCore</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">task1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">portENTER_CRITICAL e portEXIT_CRITICAL</h3>



<p class="wp-block-paragraph">As funções <code>portENTER_CRITICAL</code> e <code>portEXIT_CRITICAL</code> são usadas para proteger seções críticas de código, desativando interrupções e garantindo que nenhum outro código ou núcleo interfira enquanto a seção crítica é executada.</p>



<h4 class="wp-block-heading">Exemplo de uso:</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" data-code="portMUX_TYPE criticalMux = portMUX_INITIALIZER_UNLOCKED;

void task2(void *pvParameters) {
    while (true) {
        portENTER_CRITICAL(&amp;criticalMux);
        // Código que deve ser executado sem interferências
        printf(&quot;Tarefa 2 executando em núcleo %d\n&quot;, xPortGetCoreID());
        portEXIT_CRITICAL(&amp;criticalMux);
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}

void app_main() {
    xTaskCreatePinnedToCore(task2, &quot;Task2&quot;, 2048, NULL, 1, NULL, 1);
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">portMUX_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">criticalMux</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMUX_INITIALIZER_UNLOCKED</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">task2</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">portENTER_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">criticalMux</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Código que deve ser executado sem interferências</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa 2 executando em núcleo %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xPortGetCoreID</span><span style="color: #D8DEE9FF">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">portEXIT_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">criticalMux</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: #B48EAD">200</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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_main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreatePinnedToCore</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">task2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #B48EAD">1</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>



<h3 class="wp-block-heading">Implicações do Uso no Contexto Multicore</h3>



<ul class="wp-block-list">
<li><strong>Desempenho:</strong> Desativar interrupções pode causar atrasos, especialmente em sistemas com alta carga.</li>



<li><strong>Concorrência:</strong> Garantir acesso exclusivo evita condições de corrida (race conditions), mas deve ser usado com cuidado para não causar deadlocks.</li>



<li><strong>Multicore:</strong> No ESP32, essas funções garantem consistência ao sincronizar tarefas entre os dois núcleos, mas o uso excessivo pode prejudicar o desempenho.</li>
</ul>



<p class="wp-block-paragraph">Nesta seção, exploramos como essas funções permitem gerenciar acesso a recursos em um sistema multicore. Na próxima seção, faremos uma comparação entre essas abordagens e a diretiva <code>atomic</code> do C.</p>



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



<h2 class="wp-block-heading">Comparação com a Diretiva <code>atomic</code> do C</h2>



<p class="wp-block-paragraph">A diretiva <code>atomic</code>, introduzida no padrão C11, é uma alternativa moderna para lidar com operações atômicas. Ela oferece uma abordagem mais direta para certas tarefas em sistemas embarcados e multicore, como o ESP32. Nesta seção, compararemos as funções de controle crítico do FreeRTOS com a diretiva <code>atomic</code>, discutindo suas vantagens, limitações e melhores práticas.</p>



<h3 class="wp-block-heading">O Que é a Diretiva <code>atomic</code>?</h3>



<p class="wp-block-paragraph">A diretiva <code>atomic</code> permite realizar operações em variáveis de forma atômica, sem a necessidade de bloqueios explícitos ou desativação de interrupções. Isso é especialmente útil para incrementar, decrementar ou alterar valores compartilhados entre tarefas ou núcleos.</p>



<h4 class="wp-block-heading">Exemplo de uso com <code>atomic</code>:</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" data-code="#include <stdatomic.h&gt;

atomic_int sharedCounter = 0;

void task1(void *pvParameters) {
    while (true) {
        atomic_fetch_add(&amp;sharedCounter, 1); // Incrementa de forma atômica
        printf(&quot;Tarefa 1 incrementou o contador: %d\n&quot;, sharedCounter);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

void task2(void *pvParameters) {
    while (true) {
        atomic_fetch_sub(&amp;sharedCounter, 1); // Decrementa de forma atômica
        printf(&quot;Tarefa 2 decrementou o contador: %d\n&quot;, sharedCounter);
        vTaskDelay(150 / portTICK_PERIOD_MS);
    }
}

void app_main() {
    xTaskCreate(task1, &quot;Task1&quot;, 2048, NULL, 1, NULL);
    xTaskCreate(task2, &quot;Task2&quot;, 2048, NULL, 1, NULL);
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">stdatomic</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">atomic_int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sharedCounter</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">task1</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">atomic_fetch_add</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">sharedCounter</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 style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Incrementa de forma atômica</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa 1 incrementou o contador: %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sharedCounter</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: #B48EAD">100</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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">task2</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">atomic_fetch_sub</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">sharedCounter</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 style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Decrementa de forma atômica</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa 2 decrementou o contador: %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sharedCounter</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: #B48EAD">150</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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_main</span><span style="color: #D8DEE9FF">() </span><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">task1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">task2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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>



<h3 class="wp-block-heading">Comparação com Controle Crítico no FreeRTOS</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th><strong>Aspecto</strong></th><th><strong>Funções do FreeRTOS</strong></th><th><strong>Diretiva <code>atomic</code></strong></th></tr></thead><tbody><tr><td><strong>Complexidade</strong></td><td>Requer inicialização de mutex e controle manual</td><td>Mais simples, direto no código</td></tr><tr><td><strong>Escopo</strong></td><td>Abrange qualquer tipo de recurso ou código</td><td>Limitado a variáveis</td></tr><tr><td><strong>Desempenho</strong></td><td>Pode ser mais lento devido ao bloqueio e desbloqueio</td><td>Geralmente mais rápido para variáveis</td></tr><tr><td><strong>Compatibilidade</strong></td><td>Específico do FreeRTOS</td><td>Requer suporte do compilador (C11)</td></tr><tr><td><strong>Multicore</strong></td><td>Sincroniza entre núcleos com controle explícito</td><td>Sincronização implícita</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Quando Usar Cada Abordagem?</h3>



<ol class="wp-block-list">
<li><strong>Diretiva <code>atomic</code>:</strong>
<ul class="wp-block-list">
<li>Operações simples em variáveis, como incrementos e decrementos.</li>



<li>Cenários em que o desempenho é crítico e o suporte a C11 está garantido.</li>
</ul>
</li>



<li><strong>Funções do FreeRTOS:</strong>
<ul class="wp-block-list">
<li>Controle de acesso a recursos complexos, como periféricos ou blocos de código.</li>



<li>Garantia de exclusividade entre tarefas e núcleos.</li>
</ul>
</li>
</ol>



<h3 class="wp-block-heading">Exemplo Combinando Abordagens</h3>



<p class="wp-block-paragraph">É possível usar ambas as abordagens em um mesmo projeto, dependendo do tipo de recurso sendo protegido.</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" data-code="atomic_int sharedCounter = 0;
portMUX_TYPE criticalMux = portMUX_INITIALIZER_UNLOCKED;

void task3(void *pvParameters) {
    while (true) {
        portENTER_CRITICAL(&amp;criticalMux);
        atomic_fetch_add(&amp;sharedCounter, 1);
        printf(&quot;Task3 executando com valor atômico: %d\n&quot;, sharedCounter);
        portEXIT_CRITICAL(&amp;criticalMux);
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">atomic_int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sharedCounter</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: #D8DEE9">portMUX_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">criticalMux</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMUX_INITIALIZER_UNLOCKED</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">task3</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">portENTER_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">criticalMux</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">atomic_fetch_add</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">sharedCounter</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 style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task3 executando com valor atômico: %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sharedCounter</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">portEXIT_CRITICAL</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">criticalMux</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: #B48EAD">200</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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"/>



<h2 class="wp-block-heading">Outros Métodos de Sincronização no FreeRTOS</h2>



<p class="wp-block-paragraph">Além das funções de controle crítico e da diretiva <code>atomic</code>, o FreeRTOS oferece uma ampla gama de ferramentas para gerenciar a sincronização em sistemas embarcados multicore, como semáforos, mutexes e grupos de eventos. Nesta seção, abordaremos esses métodos, explicando seu funcionamento, vantagens e situações ideais de uso.</p>



<h3 class="wp-block-heading">1. Semáforos</h3>



<p class="wp-block-paragraph">Os semáforos são usados para sinalizar eventos ou gerenciar o acesso a recursos compartilhados. Eles podem ser binários (simples) ou de contagem (que permite múltiplos sinais).</p>



<h4 class="wp-block-heading">Exemplo: Semáforo Binário</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" data-code="#include &quot;freertos/FreeRTOS.h&quot;
#include &quot;freertos/task.h&quot;
#include &quot;freertos/semphr.h&quot;

SemaphoreHandle_t binarySemaphore;

void producerTask(void *pvParameters) {
    while (true) {
        printf(&quot;Produzindo um evento\n&quot;);
        xSemaphoreGive(binarySemaphore); // Sinaliza que o recurso está disponível
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void consumerTask(void *pvParameters) {
    while (true) {
        if (xSemaphoreTake(binarySemaphore, portMAX_DELAY)) { // Aguarda o sinal
            printf(&quot;Consumindo o evento\n&quot;);
        }
    }
}

void app_main() {
    binarySemaphore = xSemaphoreCreateBinary();
    xTaskCreate(producerTask, &quot;Producer&quot;, 2048, NULL, 1, NULL);
    xTaskCreate(consumerTask, &quot;Consumer&quot;, 2048, NULL, 1, NULL);
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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/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">freertos/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">freertos/semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">binarySemaphore</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">producerTask</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Produzindo um evento</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">binarySemaphore</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Sinaliza que o recurso está disponível</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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">consumerTask</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</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: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">binarySemaphore</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: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Aguarda o sinal</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Consumindo o evento</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: #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">app_main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">binarySemaphore</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xSemaphoreCreateBinary</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</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">producerTask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Producer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">consumerTask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Consumer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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>



<h3 class="wp-block-heading">2. Mutexes</h3>



<p class="wp-block-paragraph">Os mutexes (Mutual Exclusion) são utilizados para garantir acesso exclusivo a um recurso. Diferente de semáforos, eles podem detectar e evitar inversões de prioridade.</p>



<h4 class="wp-block-heading">Exemplo: Uso de Mutex</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" data-code="SemaphoreHandle_t resourceMutex;

void writerTask(void *pvParameters) {
    while (true) {
        if (xSemaphoreTake(resourceMutex, portMAX_DELAY)) {
            printf(&quot;Tarefa escrevendo no recurso\n&quot;);
            vTaskDelay(500 / portTICK_PERIOD_MS);
            xSemaphoreGive(resourceMutex);
        }
    }
}

void readerTask(void *pvParameters) {
    while (true) {
        if (xSemaphoreTake(resourceMutex, portMAX_DELAY)) {
            printf(&quot;Tarefa lendo o recurso\n&quot;);
            vTaskDelay(300 / portTICK_PERIOD_MS);
            xSemaphoreGive(resourceMutex);
        }
    }
}

void app_main() {
    resourceMutex = xSemaphoreCreateMutex();
    xTaskCreate(writerTask, &quot;Writer&quot;, 2048, NULL, 1, NULL);
    xTaskCreate(readerTask, &quot;Reader&quot;, 2048, NULL, 1, NULL);
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">resourceMutex</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">writerTask</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</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: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resourceMutex</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: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa escrevendo no recurso</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">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">500</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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">resourceMutex</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">readerTask</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</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: #88C0D0">xSemaphoreTake</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resourceMutex</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: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa lendo o recurso</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">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">300</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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">resourceMutex</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">app_main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">resourceMutex</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 style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">writerTask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Writer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">readerTask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Reader</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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>



<h3 class="wp-block-heading">3. Grupos de Eventos</h3>



<p class="wp-block-paragraph">Os grupos de eventos permitem sincronizar tarefas usando bits de evento. Cada tarefa pode aguardar por um ou mais bits específicos, facilitando a coordenação.</p>



<h4 class="wp-block-heading">Exemplo: Grupo de Eventos</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" data-code="#include &quot;freertos/event_groups.h&quot;

EventGroupHandle_t eventGroup;

#define EVENT_BIT_0 (1 << 0)
#define EVENT_BIT_1 (1 << 1)

void taskA(void *pvParameters) {
    while (true) {
        printf(&quot;Tarefa A sinalizando evento 0\n&quot;);
        xEventGroupSetBits(eventGroup, EVENT_BIT_0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void taskB(void *pvParameters) {
    while (true) {
        EventBits_t bits = xEventGroupWaitBits(eventGroup, EVENT_BIT_0 | EVENT_BIT_1, pdTRUE, pdFALSE, portMAX_DELAY);
        if (bits &amp; EVENT_BIT_0) {
            printf(&quot;Evento 0 detectado pela tarefa B\n&quot;);
        }
        if (bits &amp; EVENT_BIT_1) {
            printf(&quot;Evento 1 detectado pela tarefa B\n&quot;);
        }
    }
}

void app_main() {
    eventGroup = xEventGroupCreate();
    xTaskCreate(taskA, &quot;TaskA&quot;, 2048, NULL, 1, NULL);
    xTaskCreate(taskB, &quot;TaskB&quot;, 2048, NULL, 1, NULL);
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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/event_groups.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">EventGroupHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">eventGroup</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">EVENT_BIT_0</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">EVENT_BIT_1</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>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">taskA</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tarefa A sinalizando evento 0</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">xEventGroupSetBits</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">eventGroup</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVENT_BIT_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">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portTICK_PERIOD_MS</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">taskB</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">true</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">EventBits_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bits</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xEventGroupWaitBits</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">eventGroup</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVENT_BIT_0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVENT_BIT_1</span><span style="color: #ECEFF4">,</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">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 style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">bits</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVENT_BIT_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">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Evento 0 detectado pela tarefa B</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: #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">bits</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EVENT_BIT_1</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Evento 1 detectado pela tarefa B</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: #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">app_main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">eventGroup</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xEventGroupCreate</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</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">taskA</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TaskA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">taskB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TaskB</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</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: #B48EAD">1</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>



<h3 class="wp-block-heading">Comparação dos Métodos</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th><strong>Método</strong></th><th><strong>Uso Ideal</strong></th><th><strong>Vantagens</strong></th><th><strong>Desvantagens</strong></th></tr></thead><tbody><tr><td><strong>Semáforos</strong></td><td>Sinalização de eventos simples</td><td>Fácil de usar, versátil</td><td>Pode não evitar inversão de prioridade</td></tr><tr><td><strong>Mutexes</strong></td><td>Controle exclusivo de recursos</td><td>Evita inversão de prioridade</td><td>Pode causar deadlocks</td></tr><tr><td><strong>Grupos de Eventos</strong></td><td>Sincronização com múltiplos sinais</td><td>Alta flexibilidade</td><td>Maior uso de memória e complexidade</td></tr></tbody></table></figure>



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



<p class="wp-block-paragraph">Com essas ferramentas, o FreeRTOS permite uma gestão robusta de sincronização em sistemas multicore.</p>



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



<h2 class="wp-block-heading">Conclusão e Melhores Práticas</h2>



<p class="wp-block-paragraph">Neste artigo, exploramos como o FreeRTOS pode ser usado para gerenciar tarefas e recursos em sistemas multicore como o ESP32. Abordamos funções avançadas como <code>vPortCPUInitializeMutex</code>, <code>portENTER_CRITICAL</code> e <code>portEXIT_CRITICAL</code>, além de compará-las com a diretiva <code>atomic</code> do C e outros métodos de sincronização, como semáforos, mutexes e grupos de eventos.</p>



<h3 class="wp-block-heading">Principais Pontos Abordados</h3>



<ul class="wp-block-list">
<li><strong>Controle Crítico:</strong> As funções do FreeRTOS são poderosas para proteger recursos compartilhados, mas exigem um planejamento cuidadoso para evitar problemas como deadlocks e impacto no desempenho.</li>



<li><strong>Diretiva <code>atomic</code>:</strong> Uma alternativa simples e eficiente para operações em variáveis, adequada para cenários onde o suporte a C11 está disponível.</li>



<li><strong>Métodos de Sincronização:</strong> Semáforos, mutexes e grupos de eventos oferecem flexibilidade para gerenciar tarefas e recursos, permitindo projetar sistemas robustos e escaláveis.</li>
</ul>



<h3 class="wp-block-heading">Melhores Práticas no Uso do FreeRTOS no ESP32</h3>



<ol class="wp-block-list">
<li><strong>Escolha a Ferramenta Certa para Cada Situação:</strong>
<ul class="wp-block-list">
<li>Use <code>atomic</code> para operações simples em variáveis.</li>



<li>Use mutexes para controlar acesso exclusivo a recursos complexos.</li>



<li>Use semáforos e grupos de eventos para sincronização entre tarefas.</li>
</ul>
</li>



<li><strong>Evite Bloqueios Excessivos:</strong>
<ul class="wp-block-list">
<li>Limite o tempo dentro de seções críticas para minimizar atrasos.</li>



<li>Prefira abordagens não bloqueantes sempre que possível.</li>
</ul>
</li>



<li><strong>Planeje para o Contexto Multicore:</strong>
<ul class="wp-block-list">
<li>Verifique se o código é seguro para execução em múltiplos núcleos.</li>



<li>Use as ferramentas do FreeRTOS para garantir consistência e evitar condições de corrida.</li>
</ul>
</li>



<li><strong>Teste Extensivamente:</strong>
<ul class="wp-block-list">
<li>Simule cenários com alta carga para identificar possíveis falhas de sincronização.</li>



<li>Verifique o desempenho em diferentes condições para evitar gargalos.</li>
</ul>
</li>



<li><strong>Documente o Código:</strong>
<ul class="wp-block-list">
<li>Inclua comentários claros sobre o propósito de cada ferramenta usada.</li>



<li>Explique o motivo de escolhas específicas, como o uso de semáforos ou mutexes.</li>
</ul>
</li>
</ol>



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



<p class="wp-block-paragraph">Com as ferramentas apresentadas, você estará preparado para projetar sistemas confiáveis e eficientes no ESP32, aproveitando ao máximo as funcionalidades multicore do FreeRTOS.</p>



<p class="wp-block-paragraph">Esperamos que este artigo tenha sido útil e que você possa aplicá-lo em seus projetos. Caso tenha dúvidas ou sugestões, deixe seu comentário no site!</p><p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/introducao-ao-freertos-no-esp32-controle-multicore-e-recursos-avancados/">Introdução ao FreeRTOS no ESP32: Controle Multicore e Recursos Avançados</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">46</post-id>	</item>
		<item>
		<title>Peterson&#8217;s Algorithm: Uma Solução Elegante para Exclusão Mútua</title>
		<link>https://mcu.tec.br/multithreads-e-multicore/petersons-algorithm-uma-solucao-elegante-para-exclusao-mutua/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=petersons-algorithm-uma-solucao-elegante-para-exclusao-mutua</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 26 Dec 2024 16:58:02 +0000</pubDate>
				<category><![CDATA[Multithreads e Multicore]]></category>
		<category><![CDATA[Algorítimos]]></category>
		<category><![CDATA[mutex]]></category>
		<category><![CDATA[Peterson's Algorithm]]></category>
		<category><![CDATA[semáforo]]></category>
		<category><![CDATA[spinlock]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=27</guid>

					<description><![CDATA[<p>Peterson&#8217;s Algorithm é um algoritmo clássico usado em sistemas concorrentes para garantir exclusão mútua entre dois processos. Ele se destaca por sua simplicidade, eficiência e por não depender de instruções atômicas específicas do hardware, como o uso de spinlocks baseados em instruções test-and-set. Neste artigo, vamos explorar os seguintes pontos: O problema da exclusão mútua. [&#8230;]</p>
<p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/petersons-algorithm-uma-solucao-elegante-para-exclusao-mutua/">Peterson’s Algorithm: Uma Solução Elegante para Exclusão Mútua</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Peterson&#8217;s Algorithm é um algoritmo clássico usado em sistemas concorrentes para garantir <strong>exclusão mútua</strong> entre dois processos. Ele se destaca por sua simplicidade, eficiência e por não depender de instruções atômicas específicas do hardware, como o uso de <strong>spinlocks</strong> baseados em instruções <code>test-and-set</code>.</p>
<p>Neste artigo, vamos explorar os seguintes pontos:</p>
<ol>
<li>O problema da exclusão mútua.</li>
<li>Como o algoritmo de Peterson resolve este problema.</li>
<li>A relação entre Peterson&#8217;s Algorithm e spinlocks.</li>
<li>Comparação com outras soluções de exclusão mútua.</li>
<li>Exemplos práticos em código.</li>
</ol>
<hr />
<h3><strong>1. O Problema da Exclusão Mútua</strong></h3>
<p>Em sistemas com <strong>threads</strong> ou <strong>processos</strong> que compartilham recursos (como variáveis ou arquivos), pode ocorrer o problema de <strong>condições de corrida</strong>. Isso ocorre quando dois ou mais processos tentam acessar e modificar o mesmo recurso ao mesmo tempo, causando resultados imprevisíveis.</p>
<p>A <strong>exclusão mútua</strong> garante que apenas um processo possa acessar o recurso crítico por vez.</p>
<hr />
<h3><strong>2. O Algoritmo de Peterson</strong></h3>
<p>O algoritmo de Peterson é uma solução de exclusão mútua projetada para dois processos. Ele usa duas variáveis:</p>
<ul>
<li><code>flag[i]</code>: indica que o processo <code>i</code> quer entrar na seção crítica.</li>
<li><code>turn</code>: determina de quem é a vez de entrar na seção crítica.</li>
</ul>
<p>O algoritmo funciona da seguinte forma para dois processos (<code>P0</code> e <code>P1</code>):</p>
<h4><strong>Implementação do Algoritmo</strong></h4>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;pthread.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;unistd.h&gt;

#define NUM_ITERATIONS 5

bool flag[2] = {false, false};
int turn = 0;

void *process_0(void *arg) {
    for (int i = 0; i &lt; NUM_ITERATIONS; i++) {
        // Indica interesse em entrar na seção crítica
        flag[0] = true;
        turn = 1;

        // Aguarda até que o outro processo não esteja interessado ou seja sua vez
        while (flag[1] &amp;&amp; turn == 1);

        // Seção crítica
        printf("Processo 0 na seção crítica.\n");
        sleep(1);

        // Sai da seção crítica
        flag[0] = false;
    }
    return NULL;
}

void *process_1(void *arg) {
    for (int i = 0; i &lt; NUM_ITERATIONS; i++) {
        // Indica interesse em entrar na seção crítica
        flag[1] = true;
        turn = 0;

        // Aguarda até que o outro processo não esteja interessado ou seja sua vez
        while (flag[0] &amp;&amp; turn == 0);

        // Seção crítica
        printf("Processo 1 na seção crítica.\n");
        sleep(1);

        // Sai da seção crítica
        flag[1] = false;
    }
    return NULL;
}

int main() {
    pthread_t t0, t1;

    pthread_create(&amp;t0, NULL, process_0, NULL);
    pthread_create(&amp;t1, NULL, process_1, NULL);

    pthread_join(t0, NULL);
    pthread_join(t1, NULL);

    return 0;
}
</code></pre>
<hr />
<h3><strong>3. Relação com Spinlocks</strong></h3>
<p>Peterson&#8217;s Algorithm pode ser visto como uma forma rudimentar de <strong>spinlock</strong>, uma técnica onde um processo &#8220;gira&#8221; em um loop verificando continuamente se pode acessar um recurso.</p>
<h4><strong>Vantagens e Desvantagens</strong></h4>
<ul>
<li><strong>Vantagens</strong>:
<ul>
<li>Simples e eficiente para dois processos.</li>
<li>Não requer instruções atômicas específicas do hardware.</li>
</ul>
</li>
<li><strong>Desvantagens</strong>:
<ul>
<li>Não é escalável para mais de dois processos.</li>
<li>É menos eficiente que soluções modernas que usam instruções como <code>compare-and-swap</code>.</li>
</ul>
</li>
</ul>
<h4><strong>Spinlock Clássico em C</strong></h4>
<pre><code class="language-c">#include &lt;stdatomic.h&gt;
#include &lt;pthread.h&gt;
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

atomic_flag lock = ATOMIC_FLAG_INIT;

void lock_spin() {
    while (atomic_flag_test_and_set(&amp;lock)); // Gira até obter o lock
}

void unlock_spin() {
    atomic_flag_clear(&amp;lock); // Libera o lock
}

void *critical_section(void *arg) {
    lock_spin();
    printf("Thread %ld na seção crítica.\n", (long)arg);
    sleep(1);
    unlock_spin();
    return NULL;
}

int main() {
    pthread_t threads[2];

    for (long i = 0; i &lt; 2; i++) {
        pthread_create(&amp;threads[i], NULL, critical_section, (void *)i);
    }

    for (int i = 0; i &lt; 2; i++) {
        pthread_join(threads[i], NULL);
    }

    return 0;
}
</code></pre>
<hr />
<h3><strong>4. Comparação com Outras Soluções</strong></h3>
<table>
<thead>
<tr>
<th>Solução</th>
<th>Vantagens</th>
<th>Desvantagens</th>
</tr>
</thead>
<tbody>
<tr>
<td>Peterson&#8217;s Algorithm</td>
<td>Simples, não depende de hardware</td>
<td>Limitado a dois processos</td>
</tr>
<tr>
<td>Spinlock</td>
<td>Geralmente mais eficiente</td>
<td>Pode causar <strong>busy-waiting</strong></td>
</tr>
<tr>
<td>Mutex (biblioteca)</td>
<td>Abstração mais poderosa</td>
<td>Overhead adicional</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>5. Exemplos de Uso no Mundo Real</strong></h3>
<p>Embora Peterson&#8217;s Algorithm seja de interesse mais acadêmico, a ideia de exclusão mútua se aplica amplamente:</p>
<ul>
<li><strong>Mutexes e Semáforos</strong> em sistemas operacionais.</li>
<li>Controle de acesso em bases de dados.</li>
<li>Exclusão mútua em drivers de hardware.</li>
</ul>
<hr />
<h3><strong>Conclusão</strong></h3>
<p>Peterson&#8217;s Algorithm é uma solução elegante para exclusão mútua, especialmente em cenários simples. Apesar de suas limitações, sua compreensão é essencial para qualquer profissional interessado em sistemas concorrentes.</p><p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/petersons-algorithm-uma-solucao-elegante-para-exclusao-mutua/">Peterson’s Algorithm: Uma Solução Elegante para Exclusão Mútua</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">27</post-id>	</item>
		<item>
		<title>Manipulação de Variáveis Globais do Tipo float e double com Interrupções e Tasks no FreeRTOS</title>
		<link>https://mcu.tec.br/multithreads-e-multicore/manipulacao-de-variaveis-globais-do-tipo-float-e-double-com-interrupcoes-e-tasks-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=manipulacao-de-variaveis-globais-do-tipo-float-e-double-com-interrupcoes-e-tasks-no-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 26 Dec 2024 16:31:06 +0000</pubDate>
				<category><![CDATA[Multithreads e Multicore]]></category>
		<category><![CDATA[atomic]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[spinlock]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[volatile]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=24</guid>

					<description><![CDATA[<p>No desenvolvimento de sistemas embarcados com FreeRTOS, o uso de variáveis globais do tipo float e double exige atenção especial devido à natureza não atômica dessas operações e ao impacto do chaveamento de contexto. Operações matemáticas como divisão e multiplicação podem ser interrompidas, resultando em valores corrompidos. Neste artigo, abordaremos: A questão da atomicidade em [&#8230;]</p>
<p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/manipulacao-de-variaveis-globais-do-tipo-float-e-double-com-interrupcoes-e-tasks-no-freertos/">Manipulação de Variáveis Globais do Tipo float e double com Interrupções e Tasks no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h3></h3>
<p>No desenvolvimento de sistemas embarcados com FreeRTOS, o uso de variáveis globais do tipo <code>float</code> e <code>double</code> exige atenção especial devido à natureza não atômica dessas operações e ao impacto do chaveamento de contexto. Operações matemáticas como divisão e multiplicação podem ser interrompidas, resultando em valores corrompidos.</p>
<p>Neste artigo, abordaremos:</p>
<ol>
<li><strong>A questão da atomicidade em operações matemáticas.</strong></li>
<li><strong>O impacto do chaveamento de contexto.</strong></li>
<li><strong>O papel de variáveis <code>volatile</code>.</strong></li>
<li><strong>Uso do modificador <code>_Atomic</code>.</strong></li>
<li><strong>Proteções adequadas e boas práticas.</strong></li>
<li><strong>Exemplos práticos em código.</strong></li>
</ol>
<hr />
<h3>Atomicidade e Operações Matemáticas</h3>
<h4>O que é Atomicidade?</h4>
<p>Uma operação é atômica se for executada do início ao fim sem interrupções. Em sistemas multitarefa, operações não atômicas podem ser interrompidas por uma interrupção ou por outro contexto de tarefa, resultando em valores inconsistentes.</p>
<p>Por exemplo, ao realizar uma multiplicação em uma variável global:</p>
<pre><code class="language-c">global_var = global_var * factor;
</code></pre>
<p>Se essa operação for interrompida, a variável pode conter um valor intermediário inválido.</p>
<hr />
<h3>O Impacto do Chaveamento de Contexto</h3>
<p>O escalonador do FreeRTOS pode trocar entre tarefas a qualquer momento, inclusive no meio de uma operação não atômica. Isso pode levar à corrupção de dados, especialmente ao lidar com variáveis globais compartilhadas entre tarefas e interrupções.</p>
<hr />
<h3>O Papel das Variáveis <code>volatile</code></h3>
<h4>O que é <code>volatile</code>?</h4>
<p>A palavra-chave <code>volatile</code> instrui o compilador a não otimizar o acesso a uma variável, garantindo que ela seja sempre lida/escrita diretamente na memória.</p>
<h4>Limitações de <code>volatile</code></h4>
<p>Embora útil para variáveis acessadas por interrupções ou tarefas diferentes, <code>volatile</code> não garante atomicidade. Ele não protege operações compostas, como <code>global_var = global_var * factor;</code>, contra interrupções.</p>
<hr />
<h3>Uso do Modificador <code>_Atomic</code></h3>
<h4>O que é <code>_Atomic</code>?</h4>
<p>O modificador <code>_Atomic</code> é parte do padrão C11 e fornece uma maneira de declarar variáveis atômicas. Variáveis marcadas com <code>_Atomic</code> garantem que as operações sobre elas sejam realizadas de maneira atômica, evitando interrupções no meio da operação.</p>
<h4>Benefícios de <code>_Atomic</code></h4>
<ul>
<li>Elimina a necessidade de desabilitar interrupções para operações simples.</li>
<li>Pode ser combinado com funções atômicas como <code>atomic_fetch_add</code> e <code>atomic_store</code> para realizar operações seguras.</li>
</ul>
<p>Exemplo de declaração:</p>
<pre><code class="language-c">#include &lt;stdatomic.h&gt;

_Atomic float global_var = 0.0f;
</code></pre>
<h4>Operações Atômicas em Variáveis <code>_Atomic</code></h4>
<p>É possível realizar operações matemáticas seguras usando funções atômicas disponíveis no cabeçalho <code>&lt;stdatomic.h&gt;</code>:</p>
<pre><code class="language-c">#include &lt;stdatomic.h&gt;

void TaskA(void *pvParameters) {
    float factor = 2.0f;
    float local_copy;

    while (1) {
        local_copy = atomic_load(&amp;global_var);       // Carregar o valor de forma atômica
        local_copy = local_copy * factor;           // Operação local
        atomic_store(&amp;global_var, local_copy);      // Atualizar o valor de forma atômica
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
</code></pre>
<h4>Compatibilidade</h4>
<p>Embora <code>_Atomic</code> seja padrão em C11, nem todos os compiladores para sistemas embarcados o suportam completamente. É importante verificar a documentação do compilador.</p>
<hr />
<h3>Boas Práticas e Soluções</h3>
<h4>1. <strong>Uso de Mutex</strong></h4>
<p>Um Mutex pode proteger operações mais complexas envolvendo variáveis globais.</p>
<pre><code class="language-c">#include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t xMutex;
volatile float global_var;

void TaskA(void *pvParameters) {
    float factor = 1.5f;

    while (1) {
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            global_var = global_var * factor;
            xSemaphoreGive(xMutex);
        }
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
</code></pre>
<h4>2. <strong>Desabilitar Interrupções Temporariamente</strong></h4>
<p>Para operações breves:</p>
<pre><code class="language-c">taskENTER_CRITICAL();
global_var = global_var / factor;
taskEXIT_CRITICAL();
</code></pre>
<h4>3. <strong>Combinação com <code>_Atomic</code></strong></h4>
<p>Ao usar <code>_Atomic</code>, muitas vezes não é necessário desabilitar interrupções ou usar mutexes para operações simples.</p>
<hr />
<h3>Exemplo Completo com <code>_Atomic</code></h3>
<p>Abaixo, um exemplo que combina <code>_Atomic</code> e FreeRTOS para garantir a manipulação segura de uma variável <code>float</code> global:</p>
<pre><code class="language-c">#include &lt;stdatomic.h&gt;
#include "FreeRTOS.h"
#include "task.h"

_Atomic float global_var = 0.0f;

void TaskA(void *pvParameters) {
    float factor = 2.5f;
    float local_var;

    while (1) {
        local_var = atomic_load(&amp;global_var);       // Carregar valor
        local_var = local_var * factor;            // Operação local
        atomic_store(&amp;global_var, local_var);      // Atualizar valor
        vTaskDelay(pdMS_TO_TICKS(100));            // Aguardar 100ms
    }
}

void TaskB(void *pvParameters) {
    float divisor = 1.2f;
    float local_var;

    while (1) {
        local_var = atomic_load(&amp;global_var);       // Carregar valor
        local_var = local_var / divisor;           // Operação local
        atomic_store(&amp;global_var, local_var);      // Atualizar valor
        vTaskDelay(pdMS_TO_TICKS(200));            // Aguardar 200ms
    }
}

int main(void) {
    xTaskCreate(TaskA, "TaskA", 1000, NULL, 1, NULL);
    xTaskCreate(TaskB, "TaskB", 1000, NULL, 1, NULL);
    vTaskStartScheduler();

    for (;;);
    return 0;
}
</code></pre>
<hr />
<h3>Conclusão</h3>
<p>Usar <code>_Atomic</code> é uma solução moderna e eficiente para manipular variáveis globais em sistemas multitarefa com FreeRTOS. Ele elimina a necessidade de técnicas manuais mais complexas para garantir atomicidade em operações simples. No entanto, para operações mais complexas, o uso de Mutex ou a combinação com desabilitação de interrupções ainda pode ser necessário.</p>
<p>Sempre verifique o suporte ao padrão C11 no compilador utilizado e teste rigorosamente para garantir a confiabilidade em sistemas críticos.</p><p>The post <a href="https://mcu.tec.br/multithreads-e-multicore/manipulacao-de-variaveis-globais-do-tipo-float-e-double-com-interrupcoes-e-tasks-no-freertos/">Manipulação de Variáveis Globais do Tipo float e double com Interrupções e Tasks 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">24</post-id>	</item>
	</channel>
</rss>
