<?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>semáforo - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/semaforo/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Fri, 02 May 2025 01:02:28 +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>semáforo - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões no FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 02 May 2025 14:00:00 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[concorrência]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[escalonador]]></category>
		<category><![CDATA[filósofos glutões]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[herança de prioridade]]></category>
		<category><![CDATA[microcontrolador]]></category>
		<category><![CDATA[mutex]]></category>
		<category><![CDATA[padrões de projeto RTOS]]></category>
		<category><![CDATA[prioridade]]></category>
		<category><![CDATA[priority ceiling]]></category>
		<category><![CDATA[semáforo]]></category>
		<category><![CDATA[sincronização de tarefas]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[starvation]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=475</guid>

					<description><![CDATA[<p>Aprenda a evitar deadlock e starvation em microcontroladores com FreeRTOS. Veja soluções práticas com mutexes e semáforos no clássico problema dos Filósofos.</p>
<p>The post <a href="https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/">Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">O gerenciamento de concorrência em sistemas embarcados de tempo real impõe desafios cruciais para a segurança, desempenho e previsibilidade do sistema. Problemas como <em>deadlock</em> (interbloqueio) e <em>starvation</em> (inanição) surgem quando múltiplas tarefas competem por recursos limitados, podendo comprometer deadlines e a confiabilidade do sistema. Neste artigo, exploramos esses problemas com foco em microcontroladores executando o FreeRTOS, ilustrando os conceitos através do clássico problema dos Filósofos Glutões. Apresentamos os padrões de projeto e estratégias de implementação sugeridas por Bruce Powel Douglass para evitar tais falhas, com exemplos práticos e didáticos.</p>



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



<h3 class="wp-block-heading"><strong>Problema a Ser Resolvido</strong></h3>



<p class="wp-block-paragraph">Sistemas embarcados frequentemente operam em ambientes com recursos escassos e múltiplas tarefas concorrentes, tornando a coordenação entre tarefas crítica para garantir a execução correta. <em>Deadlock</em> ocorre quando duas ou mais tarefas estão esperando indefinidamente por recursos que nunca serão liberados, devido a um ciclo de espera circular. Já a <em>starvation</em> ocorre quando uma tarefa de baixa prioridade é perpetuamente preterida, nunca tendo a chance de acessar os recursos que precisa.</p>



<p class="wp-block-paragraph">Esses problemas são agravados em sistemas de tempo real, pois atrasos não planejados podem resultar em falhas catastróficas. Em contextos como o FreeRTOS, que utiliza escalonamento por prioridade, essas questões se tornam ainda mais relevantes. Entender as condições que causam esses problemas e aplicar padrões de projeto adequados é fundamental para evitar falhas imprevisíveis.</p>



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



<h3 class="wp-block-heading"><strong>Estrutura do Padrão</strong></h3>



<p class="wp-block-paragraph">Um dos exemplos clássicos usados para ilustrar <em>deadlock</em> é o problema dos <strong>Filósofos Glutões</strong>. Nele, cinco filósofos sentam-se à mesa, cada um com um garfo à sua direita e esquerda, e precisam de ambos para comer. Se todos pegam um garfo e esperam o outro, ninguém come — ocorre um <em>deadlock</em>.</p>



<p class="wp-block-paragraph">No contexto do FreeRTOS, esse problema se manifesta quando tarefas compartilham múltiplos recursos (por exemplo, semáforos ou mutexes) e os bloqueiam em ordens diferentes. Bruce Douglass apresenta padrões como <em>Simultaneous Locking</em>, <em>Ordered Locking</em> e <em>Priority Ceiling</em> como soluções. Cada um quebra uma ou mais das quatro condições necessárias para o deadlock:</p>



<ol class="wp-block-list">
<li>Exclusão mútua;</li>



<li>Posse e espera (hold and wait);</li>



<li>Não-preempção;</li>



<li>Espera circularReal-Time Design Patter….</li>
</ol>



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



<h3 class="wp-block-heading"><strong>Papéis de Colaboração (Collaboration Roles)</strong></h3>



<ul class="wp-block-list">
<li><strong>Tarefas (Threads)</strong>: Agentes ativos que requerem acesso a recursos compartilhados.</li>



<li><strong>Scheduler (Escalonador)</strong>: Gerencia as prioridades das tarefas no FreeRTOS.</li>



<li><strong>Mutex/Semáforos</strong>: Controlam o acesso a recursos não-reentrantes.</li>



<li><strong>Shared Resource</strong>: Qualquer dado ou periférico que precise ser protegido.</li>



<li><strong>Task Control Block (TCB)</strong>: Armazena estado, prioridade e contexto de cada tarefa.</li>
</ul>



<h3 class="wp-block-heading"><strong>Consequências</strong></h3>



<p class="wp-block-paragraph">O impacto da ocorrência de <em>deadlock</em> e <em>starvation</em> em sistemas embarcados pode ser catastrófico. Quando tarefas ficam permanentemente bloqueadas, recursos permanecem indisponíveis e o sistema pode parar completamente ou deixar de responder dentro do prazo esperado — o que, em aplicações críticas, como controle industrial ou dispositivos médicos, pode gerar danos materiais ou colocar vidas em risco.</p>



<p class="wp-block-paragraph">No caso do <em>deadlock</em>, a principal consequência é a <strong>paralisação do sistema</strong>, mesmo com o processador ativo. O scheduler do FreeRTOS pode continuar operando, mas as tarefas envolvidas no ciclo de espera nunca prosseguem. Já na <em>starvation</em>, embora o sistema permaneça funcional, uma ou mais tarefas de baixa prioridade <strong>jamais obtêm acesso aos recursos</strong>, resultando em degradação progressiva do desempenho ou falhas intermitentes difíceis de diagnosticar.</p>



<p class="wp-block-paragraph">Outra consequência importante é a dificuldade de <strong>debug e validação de sistemas embarcados</strong> com problemas intermitentes de bloqueio. Tais problemas não são facilmente reproduzíveis, pois dependem da ordem de execução das tarefas, que pode variar conforme as condições de tempo real.</p>



<p class="wp-block-paragraph">Além disso, <em>starvation</em> é frequentemente associada à <strong>inversão de prioridade</strong>, onde uma tarefa de alta prioridade fica bloqueada esperando uma de baixa prioridade liberar um recurso. Isso pode ser agravado em sistemas com escalonamento por prioridade fixa, como o FreeRTOS, a menos que sejam adotados mecanismos como o <strong>herdamento de prioridade (priority inheritance)</strong> ou <strong>teto de prioridade (priority ceiling)</strong>.</p>



<p class="wp-block-paragraph">Portanto, as consequências não são apenas técnicas — elas impactam diretamente os critérios de qualidade e confiabilidade do projeto.</p>



<h3 class="wp-block-heading"><strong>Estratégias de Implementação</strong></h3>



<p class="wp-block-paragraph">Prevenir <em>deadlocks</em> e <em>starvation</em> exige disciplina na coordenação do acesso a recursos e a aplicação de padrões de projeto consolidados. No contexto do FreeRTOS, onde tarefas operam em diferentes níveis de prioridade e disputam semáforos, mutexes ou filas, a implementação correta dos mecanismos de sincronização é essencial.</p>



<h4 class="wp-block-heading"><strong>1. Evitando Deadlock com Ordenação de Locks</strong></h4>



<p class="wp-block-paragraph">A estratégia mais direta para evitar <em>deadlocks</em> é <strong>padronizar a ordem de aquisição de recursos</strong>. Se todas as tarefas adquirirem os recursos sempre na mesma ordem (por exemplo, do recurso A para o B), a condição de espera circular é evitada. Este padrão é conhecido como <strong>Ordered Locking Pattern</strong>, amplamente discutido por Douglass em Real-Time Design Patter.</p>



<pre class="wp-block-preformatted"><code>// Exemplo de ordenação de mutexes no FreeRTOS<br>void Task1(void *pvParameters) {<br>    for (;;) {<br>        xSemaphoreTake(mutexA, portMAX_DELAY);<br>        xSemaphoreTake(mutexB, portMAX_DELAY);<br><br>        // Região crítica usando os dois recursos<br><br>        xSemaphoreGive(mutexB);<br>        xSemaphoreGive(mutexA);<br>    }<br>}<br></code></pre>



<p class="wp-block-paragraph">Todas as tarefas devem respeitar a mesma ordem <code>A -&gt; B</code> ao adquirir múltiplos recursos.</p>



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



<h4 class="wp-block-heading"><strong>2. Evitando Starvation com Herdamento de Prioridade</strong></h4>



<p class="wp-block-paragraph">Quando uma tarefa de alta prioridade espera por um mutex que está com uma tarefa de baixa prioridade, pode haver <em>starvation</em> por inversão de prioridade. O FreeRTOS possui <strong>mutexes com herança de prioridade</strong> (<code>xSemaphoreCreateMutex</code>) justamente para mitigar esse problema.</p>



<pre class="wp-block-preformatted"><code>SemaphoreHandle_t xMutex;<br><br>void vSetup() {<br>    xMutex = xSemaphoreCreateMutex(); // já inclui herança de prioridade<br>}<br></code></pre>



<p class="wp-block-paragraph">Neste mecanismo, a tarefa de baixa prioridade “empresta” sua prioridade para igualar à da tarefa que está bloqueada, impedindo que tarefas intermediárias a impeçam de prosseguir e liberar o recurso.</p>



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



<h4 class="wp-block-heading"><strong>3. Timeout e Deadlock Detectável</strong></h4>



<p class="wp-block-paragraph">Adicionar timeouts ao uso de mutexes pode ajudar a identificar cenários de <em>deadlock</em> em tempo de execução. Embora não evite o problema, permite detectar que algo saiu do esperado.</p>



<pre class="wp-block-preformatted"><code>if (xSemaphoreTake(mutexA, pdMS_TO_TICKS(100)) == pdFALSE) {<br>    // Erro: recurso não obtido — possível deadlock<br>    vHandleDeadlockError();<br>}<br></code></pre>



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



<h4 class="wp-block-heading"><strong>4. Solução Filósofos Glutões com Recurso Central</strong></h4>



<p class="wp-block-paragraph">Um exemplo clássico é substituir os mutexes laterais por um <strong>recurso central</strong> ou um semáforo de contagem (counting semaphore), limitando o número máximo de filósofos que podem pegar os garfos ao mesmo tempo.</p>



<pre class="wp-block-preformatted">SemaphoreHandle_t semGarfos;<br><br>void vInit() {<br>    semGarfos = xSemaphoreCreateCounting(4, 4); // 5 filósofos, 4 permissões<br>}<br><br>void Filosofo(void *pvParameters) {<br>    for (;;) {<br>        pensar();<br><br>        xSemaphoreTake(semGarfos, portMAX_DELAY);<br>        xSemaphoreTake(garfoEsquerda, portMAX_DELAY);<br>        xSemaphoreTake(garfoDireita, portMAX_DELAY);<br><br>        comer();<br><br>        xSemaphoreGive(garfoDireita);<br>        xSemaphoreGive(garfoEsquerda);<br>        xSemaphoreGive(semGarfos);<br>    }<br>}<br></pre>



<p class="wp-block-paragraph">Esse padrão evita <em>deadlock</em> ao garantir que no máximo 4 filósofos estejam tentando pegar dois garfos, sempre sobrando ao menos um.</p>



<h3 class="wp-block-heading"><strong>Padrões Relacionados</strong></h3>



<p class="wp-block-paragraph">A prevenção eficaz de <em>deadlocks</em> e <em>starvation</em> não depende apenas da ordem ou da prioridade, mas também do uso inteligente de padrões complementares que podem ser combinados para diferentes necessidades de sincronização. Bruce Powel Douglass apresenta um conjunto de padrões especialmente aplicáveis a sistemas de tempo real como os que usam o FreeRTOS:</p>



<h4 class="wp-block-heading"><strong>1. Guarded Call Pattern</strong></h4>



<p class="wp-block-paragraph">Esse padrão garante que a chamada a um recurso protegido só ocorra quando sua condição estiver satisfeita, evitando bloqueios desnecessários. Ele frequentemente usa sinais (flags ou semáforos binários) para proteger regiões críticas, reduzindo a chance de deadlocks ao evitar bloqueios longos.</p>



<pre class="wp-block-preformatted"><code>if (xSemaphoreTake(xRecurso, 0) == pdTRUE) {<br>    acessarRecurso();<br>    xSemaphoreGive(xRecurso);<br>} else {<br>    // Recurso indisponível, decide-se agir de outra forma<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>2. Simultaneous Locking Pattern</strong></h4>



<p class="wp-block-paragraph">Este padrão representa um cenário onde múltiplos recursos são adquiridos simultaneamente — situação comum no problema dos Filósofos Glutões. A solução consiste em sempre adquirir todos os recursos de uma vez (por exemplo, usando semáforo de contagem ou buffers predefinidos), ou falhar imediatamente caso isso não seja possível, evitando a espera bloqueante.</p>



<pre class="wp-block-preformatted"><code>bool lock_all() {<br>    if (xSemaphoreTake(mutexA, 0) == pdTRUE) {<br>        if (xSemaphoreTake(mutexB, 0) == pdTRUE) {<br>            return true;<br>        } else {<br>            xSemaphoreGive(mutexA);<br>        }<br>    }<br>    return false;<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>3. Priority Ceiling Pattern</strong></h4>



<p class="wp-block-paragraph">Muito eficaz contra <em>inversão de prioridade</em>, esse padrão eleva a prioridade de uma tarefa sempre que ela adquire um recurso compartilhado, ao nível da mais alta prioridade possível que pode usar o recurso. Essa estratégia exige mais controle, mas evita inversões e starvation sem necessidade de herança dinâmica de prioridade.</p>



<p class="wp-block-paragraph">O FreeRTOS não implementa esse padrão nativamente, mas ele pode ser simulado ajustando temporariamente a prioridade da tarefa:</p>



<pre class="wp-block-preformatted"><code>void accessResource() {<br>    UBaseType_t oldPrio = uxTaskPriorityGet(NULL);<br>    vTaskPrioritySet(NULL, PRIORITY_CEILING);<br><br>    usarRecursoCompartilhado();<br><br>    vTaskPrioritySet(NULL, oldPrio);<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>4. Static Priority Pattern</strong></h4>



<p class="wp-block-paragraph">Este padrão, também documentado por DouglassReal-Time Design Patter…, recomenda que os níveis de prioridade sejam cuidadosamente atribuídos e fixos durante a operação. Isso facilita a verificação de <em>schedulability</em> e evita condições dinâmicas imprevisíveis que podem agravar a starvation.</p>



<h3 class="wp-block-heading"><strong>Modelo de Amostragem: O Problema dos Filósofos Glutões com FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Vamos aplicar os conceitos discutidos em um exemplo prático no FreeRTOS: uma simulação do problema dos <strong>Filósofos Glutões</strong>, ilustrando tanto o problema quanto a solução com semáforo de contagem — uma estratégia segura para evitar <em>deadlock</em>.</p>



<h4 class="wp-block-heading"><strong>Configuração</strong></h4>



<ul class="wp-block-list">
<li><strong>5 tarefas</strong> representando os filósofos.</li>



<li>Cada filósofo precisa pegar dois garfos (mutexes) para comer.</li>



<li>Usa-se um <strong>Counting Semaphore com valor 4</strong>, limitando o número de filósofos com permissão para tentar pegar os garfos ao mesmo tempo.</li>



<li>Cada garfo é um mutex (representando um recurso compartilhado).</li>
</ul>



<pre class="wp-block-preformatted"><code>#include "FreeRTOS.h"<br>#include "task.h"<br>#include "semphr.h"<br><br>#define NUM_FILOSOFOS 5<br><br>SemaphoreHandle_t garfos[NUM_FILOSOFOS];<br>SemaphoreHandle_t semPermissao;<br><br>void pensar(int id) {<br>    printf("Filósofo %d está pensando...\n", id);<br>    vTaskDelay(pdMS_TO_TICKS(500 + id * 100));<br>}<br><br>void comer(int id) {<br>    printf("Filósofo %d está comendo!\n", id);<br>    vTaskDelay(pdMS_TO_TICKS(300));<br>}<br><br>void Filosofo(void *pvParameters) {<br>    int id = (int) pvParameters;<br>    int garfoEsquerda = id;<br>    int garfoDireita = (id + 1) % NUM_FILOSOFOS;<br><br>    for (;;) {<br>        pensar(id);<br><br>        // Espera por permissão para tentar pegar os dois garfos<br>        xSemaphoreTake(semPermissao, portMAX_DELAY);<br><br>        // Pega garfos (ordem fixa: esquerda depois direita)<br>        xSemaphoreTake(garfos[garfoEsquerda], portMAX_DELAY);<br>        xSemaphoreTake(garfos[garfoDireita], portMAX_DELAY);<br><br>        comer(id);<br><br>        // Libera garfos<br>        xSemaphoreGive(garfos[garfoDireita]);<br>        xSemaphoreGive(garfos[garfoEsquerda]);<br><br>        // Libera permissão<br>        xSemaphoreGive(semPermissao);<br>    }<br>}<br><br>void main_app() {<br>    semPermissao = xSemaphoreCreateCounting(NUM_FILOSOFOS - 1, NUM_FILOSOFOS - 1);<br><br>    for (int i = 0; i &lt; NUM_FILOSOFOS; i++) {<br>        garfos[i] = xSemaphoreCreateMutex();<br>    }<br><br>    for (int i = 0; i &lt; NUM_FILOSOFOS; i++) {<br>        char nome[16];<br>        sprintf(nome, "Filosofo%d", i);<br>        xTaskCreate(Filosofo, nome, configMINIMAL_STACK_SIZE, (void *)i, 1, NULL);<br>    }<br><br>    vTaskStartScheduler();<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>Resultado</strong></h4>



<p class="wp-block-paragraph">Neste modelo, <strong>evitamos o deadlock</strong> limitando o número de filósofos que podem competir por garfos a quatro. Assim, sempre haverá ao menos um garfo disponível, quebrando a condição de espera circular. Ao mesmo tempo, garantimos <em>fairness</em> entre tarefas com prioridade igual, evitando <em>starvation</em> em função da ordem de execução.</p>



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



<h3 class="wp-block-heading"><strong>Conclusão</strong></h3>



<p class="wp-block-paragraph">Ao trazer os clássicos problemas da ciência da computação como o dos Filósofos Glutões para o contexto de sistemas embarcados com FreeRTOS, reforçamos a importância de padrões de projeto adequados para lidar com concorrência. Evitar <em>deadlock</em> e <em>starvation</em> é essencial para garantir sistemas previsíveis, seguros e eficientes. Estratégias como ordenação de locks, uso de semáforos de contagem, herança de prioridade e padrões como <em>Guarded Call</em> e <em>Priority Ceiling</em> devem fazer parte do repertório de todo engenheiro de firmware.</p><p>The post <a href="https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/">Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões 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">475</post-id>	</item>
		<item>
		<title></title>
		<link>https://mcu.tec.br/rtos/66-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=66-2</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Mon, 10 Feb 2025 19:57:35 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[barramento de comunicação]]></category>
		<category><![CDATA[comunicação I2C]]></category>
		<category><![CDATA[comunicação SPI]]></category>
		<category><![CDATA[controle de concorrência]]></category>
		<category><![CDATA[desenvolvimento embarcado]]></category>
		<category><![CDATA[exclusão mútua]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[interrupções]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[multitarefa]]></category>
		<category><![CDATA[multitasking]]></category>
		<category><![CDATA[mutex]]></category>
		<category><![CDATA[programação em C]]></category>
		<category><![CDATA[programação embarcada]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[semáforo]]></category>
		<category><![CDATA[sincronização de tarefas]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[STM32F411RE]]></category>
		<category><![CDATA[suspensão do escalonador]]></category>
		<category><![CDATA[tempo real]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=66</guid>

					<description><![CDATA[<p>A programação multitarefa traz diversos desafios, e um dos principais é a sincronização de tarefas que acessam recursos compartilhados. Quando múltiplas threads ou processos precisam interagir com os mesmos dados ou dispositivos, é essencial garantir que essa interação ocorra de forma segura, evitando condições de corrida e corrupção de dados. Para isso, três técnicas são [&#8230;]</p>
<p>The post <a href="https://mcu.tec.br/rtos/66-2/"></a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">A programação multitarefa traz diversos desafios, e um dos principais é a sincronização de tarefas que acessam recursos compartilhados. Quando múltiplas threads ou processos precisam interagir com os mesmos dados ou dispositivos, é essencial garantir que essa interação ocorra de forma segura, evitando condições de corrida e corrupção de dados.</p>



<p class="wp-block-paragraph">Para isso, três técnicas são amplamente utilizadas: <em>mutex</em>, <em>semáforos</em> e a suspensão do escalonador. Cada uma dessas abordagens tem seu melhor momento de aplicação e, se usada de maneira inadequada, pode levar a problemas de desempenho ou até mesmo a falhas difíceis de depurar. Neste artigo, exploraremos quando e como usar cada uma delas, incluindo exemplos práticos para facilitar a compreensão.</p>



<h2 class="wp-block-heading"><strong>Mutex: Exclusão Mútua para Recursos Compartilhados</strong></h2>



<p class="wp-block-paragraph">O <em>mutex</em> (mutual exclusion) é um mecanismo utilizado para garantir que apenas uma tarefa por vez tenha acesso a um recurso compartilhado. Ele funciona como um cadeado: a primeira tarefa que o adquire pode continuar a execução, enquanto as demais precisam aguardar sua liberação.</p>



<h3 class="wp-block-heading"><strong>Quando Usar Mutex</strong></h3>



<ul class="wp-block-list">
<li>Quando há um recurso que <strong>não pode ser acessado simultaneamente</strong> por mais de uma tarefa.</li>



<li>Para garantir <strong>consistência de dados</strong> ao modificar variáveis compartilhadas.</li>



<li>Em sistemas operacionais com <strong>preempção</strong> habilitada, onde uma tarefa pode ser interrompida a qualquer momento.</li>
</ul>



<h3 class="wp-block-heading"><strong>Quando Evitar Mutex</strong></h3>



<ul class="wp-block-list">
<li>Quando há <strong>altíssima concorrência</strong>, pois as tarefas podem passar muito tempo bloqueadas, reduzindo o desempenho.</li>



<li>Quando um recurso pode ser acessado de forma <strong>não exclusiva</strong>, ou seja, múltiplas tarefas podem lê-lo sem problemas.</li>



<li>Quando há risco de <strong>deadlocks</strong>, onde múltiplas tarefas ficam bloqueadas esperando a liberação de mutexes que nunca ocorrerão.</li>
</ul>



<h3 class="wp-block-heading"><strong>Exemplo de Uso de Mutex no STM32F411RE com FreeRTOS</strong></h3>



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

SemaphoreHandle_t xMutex;
int shared_resource = 0;

void Task1(void *pvParameters) {
    while(1) {
         if (xSemaphoreTake(xMutex, portMAX_DELAY)) {
                    shared_resource++;
                    printf(&quot;Task1: Recurso compartilhado = %d\n&quot;, shared_resource);
                    xSemaphoreGive(xMutex);
          }
          vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void Task2(void *pvParameters) {
    while(1) {
            if (xSemaphoreTake(xMutex, portMAX_DELAY)) {
                      shared_resource--;
                      printf(&quot;Task2: Recurso compartilhado = %d\n&quot;, shared_resource);
                      xSemaphoreGive(xMutex);
            }
           vTaskDelay(pdMS_TO_TICKS(500));
     }
}

int main() {
    xMutex = xSemaphoreCreateMutex();
    if (xMutex != NULL) {
            xTaskCreate(Task1, &quot;Task 1&quot;, 128, NULL, 1, NULL);
            xTaskCreate(Task2, &quot;Task 2&quot;, 128, NULL, 1, NULL);
            vTaskStartScheduler()
    }
    while(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: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">stm32f4xx.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> xMutex</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> shared_resource </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: #ECEFF4">(</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: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    shared_resource</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">printf</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task1: Recurso compartilhado = %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> shared_resource</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xMutex</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1000</span><span style="color: #ECEFF4">))</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: #ECEFF4">(</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: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                      shared_resource</span><span style="color: #81A1C1">--;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                      </span><span style="color: #88C0D0">printf</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task2: Recurso compartilhado = %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> shared_resource</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                      </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xMutex</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">           </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">500</span><span style="color: #ECEFF4">))</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">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xMutex </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xSemaphoreCreateMutex</span><span style="color: #ECEFF4">()</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: #ECEFF4">(</span><span style="color: #D8DEE9FF">xMutex </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">NULL</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #D8DEE9FF">Task1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task 1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">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: #81A1C1">NULL</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">Task2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task 2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">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: #81A1C1">NULL</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">vTaskStartScheduler</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



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



<h2 class="wp-block-heading"><strong>Semáforos: Controle de Fluxo e Contagem de Recursos</strong></h2>



<p class="wp-block-paragraph">Os <em>semáforos</em> são estruturas mais flexíveis que os mutexes e podem ser usados para diferentes propósitos. Eles operam com um contador interno, que pode permitir múltiplas tarefas acessando um mesmo recurso, dependendo da configuração.</p>



<h3 class="wp-block-heading"><strong>Quando Usar Semáforos</strong></h3>



<ul class="wp-block-list">
<li>Para <strong>controlar múltiplas instâncias</strong> de um recurso compartilhado, como um conjunto de conexões disponíveis em um servidor.</li>



<li>Para <strong>sincronizar tarefas</strong>, permitindo que uma aguarde a outra concluir uma operação antes de continuar.</li>



<li>Em sistemas embarcados onde múltiplas tarefas precisam se comunicar sem causar bloqueios desnecessários.</li>
</ul>



<h3 class="wp-block-heading"><strong>Quando Evitar Semáforos</strong></h3>



<ul class="wp-block-list">
<li>Quando há necessidade de <strong>exclusão mútua</strong>. Um semáforo mal configurado pode permitir que múltiplas tarefas acessem um recurso crítico simultaneamente.</li>



<li>Quando o código não foi planejado corretamente, podendo levar a <strong>inconsistências difíceis de depurar</strong>.</li>



<li>Quando há possibilidade de <strong>inversão de prioridade</strong>, onde tarefas de baixa prioridade podem atrasar a execução de tarefas mais importantes.</li>
</ul>



<h3 class="wp-block-heading"><strong>Exemplo de Uso de Semáforo no STM32F411RE com FreeRTOS</strong></h3>



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

SemaphoreHandle_t xSemaphore;
int shared_counter = 0;

void Task1(void *pvParameters) {
    while(1) {
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY)) {
            shared_counter++;
            printf(&quot;Task1: Contador = %d\n&quot;, shared_counter);
            xSemaphoreGive(xSemaphore);
        }
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

void Task2(void *pvParameters) {
    while(1) {
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY)) {
            shared_counter--;
            printf(&quot;Task2: Contador = %d\n&quot;, shared_counter);
            xSemaphoreGive(xSemaphore);
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main() {
    xSemaphore = xSemaphoreCreateBinary();
    xSemaphoreGive(xSemaphore);
    if (xSemaphore != NULL) {
        xTaskCreate(Task1, &quot;Task 1&quot;, 128, NULL, 1, NULL);
        xTaskCreate(Task2, &quot;Task 2&quot;, 128, NULL, 1, NULL);
        vTaskStartScheduler();
    }
    while(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: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">stm32f4xx.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> xSemaphore</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> shared_counter </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: #ECEFF4">(</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: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            shared_counter</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task1: Contador = %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> shared_counter</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">500</span><span style="color: #ECEFF4">))</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: #ECEFF4">(</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: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            shared_counter</span><span style="color: #81A1C1">--;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task2: Contador = %d</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> shared_counter</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1000</span><span style="color: #ECEFF4">))</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">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    xSemaphore </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">xSemaphoreCreateBinary</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #D8DEE9FF">xSemaphore </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">NULL</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #D8DEE9FF">Task1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task 1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">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: #81A1C1">NULL</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">Task2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Task 2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">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: #81A1C1">NULL</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskStartScheduler</span><span style="color: #ECEFF4">()</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">while</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading"><strong>Suspensão do Escalonador: Controle Total com Custo Alto</strong></h2>



<p class="wp-block-paragraph">A suspensão do escalonador (<em>scheduler lock</em>) é uma abordagem mais extrema, onde o sistema operacional pausa a troca de tarefas, garantindo que a tarefa em execução complete seu trabalho sem interrupções.</p>



<h3 class="wp-block-heading"><strong>Quando Usar a Suspensão do Escalonador</strong></h3>



<ul class="wp-block-list">
<li>Quando uma operação crítica <strong>precisa ser executada em um curto período de tempo</strong> e <strong>não pode ser interrompida</strong>.</li>



<li>Para <strong>seções de código extremamente curtas</strong> e atômicas, onde o impacto da suspensão do escalonador é mínimo.</li>



<li>Em sistemas <em>bare-metal</em> sem suporte a mutexes ou semáforos.</li>
</ul>



<h3 class="wp-block-heading"><strong>Quando Evitar a Suspensão do Escalonador</strong></h3>



<ul class="wp-block-list">
<li>Quando há <strong>tarefas de tempo real</strong> que precisam responder rapidamente a eventos externos.</li>



<li>Se o código protegido for <strong>muito longo</strong>, pois a suspensão prolongada do escalonador pode causar degradação significativa no desempenho do sistema.</li>



<li>Em sistemas onde múltiplas CPUs são usadas, pois suspender o escalonador em um núcleo não impede que outros núcleos executem tarefas concorrentes.</li>
</ul>



<h3 class="wp-block-heading"><strong>Exemplo de Suspensão do Escalonador no STM32F411RE com FreeRTOS</strong></h3>



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

void CriticalTask(void *pvParameters) {
    while(1) {
        vTaskSuspendAll(); // Suspende o escalonador
        // Código crítico
        printf(&quot;Executando tarefa crítica\n&quot;);
        xTaskResumeAll(); // Retoma o escalonador
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main() {
    xTaskCreate(CriticalTask, &quot;Critical Task&quot;, 128, NULL, 1, NULL);
    vTaskStartScheduler();
    while(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: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">CriticalTask</span><span style="color: #ECEFF4">(</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: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskSuspendAll</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #616E88"> // Suspende o escalonador</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Código crítico</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Executando tarefa crítica</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xTaskResumeAll</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #616E88"> // Retoma o escalonador</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1000</span><span style="color: #ECEFF4">))</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">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #ECEFF4">()</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: #ECEFF4">(</span><span style="color: #D8DEE9FF">CriticalTask</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Critical Task</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">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: #81A1C1">NULL</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vTaskStartScheduler</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading"><strong>Abordagem para Dispositivos I2C e SPI</strong></h2>



<p class="wp-block-paragraph">Os protocolos de comunicação como <strong>I2C</strong> e <strong>SPI</strong> são amplamente utilizados em sistemas embarcados para comunicação entre microcontroladores e periféricos. A abordagem correta para controle de concorrência depende do tipo de comunicação e do contexto de uso.</p>



<h3 class="wp-block-heading"><strong>I2C com Mutex no STM32F411RE</strong></h3>



<p class="wp-block-paragraph">O protocolo <strong>I2C</strong> é um barramento compartilhado onde múltiplos dispositivos podem estar conectados ao mesmo controlador. Como apenas um dispositivo pode realizar a comunicação por vez, o uso de <strong>mutex</strong> é essencial para evitar colisões entre tarefas concorrentes que tentam acessar o barramento ao mesmo tempo.</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="#include &quot;stm32f4xx_hal.h&quot;
#include &quot;FreeRTOS.h&quot;
#include &quot;semphr.h&quot;

I2C_HandleTypeDef hi2c1;
SemaphoreHandle_t i2cMutex;

void I2C_Write(uint16_t devAddress, uint8_t *data, uint16_t size) {
    if (xSemaphoreTake(i2cMutex, portMAX_DELAY)) {
        HAL_I2C_Master_Transmit(&amp;hi2c1, devAddress, data, size, HAL_MAX_DELAY);
        xSemaphoreGive(i2cMutex);
    }
}
" 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: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">stm32f4xx_hal.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">I2C_HandleTypeDef hi2c1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #8FBCBB">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> i2cMutex</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">I2C_Write</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">devAddress</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">size</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">i2cMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">HAL_I2C_Master_Transmit</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF">hi2c1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> devAddress</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> size</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> HAL_MAX_DELAY</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">i2cMutex</span><span style="color: #ECEFF4">)</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>



<h3 class="wp-block-heading"><strong>SPI com Mutex no STM32F411RE</strong></h3>



<p class="wp-block-paragraph">O protocolo <strong>SPI</strong> geralmente é mais rápido que o I2C, mas também pode sofrer de concorrência quando múltiplas tarefas tentam acessá-lo simultaneamente. O uso de <strong>mutex</strong> impede que duas tarefas interfiram uma na outra enquanto utilizam o barramento SPI.</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="#include &quot;stm32f4xx_hal.h&quot;
#include &quot;FreeRTOS.h&quot;
#include &quot;semphr.h&quot;

SPI_HandleTypeDef hspi1;
SemaphoreHandle_t spiMutex;

void SPI_Write(uint8_t *data, uint16_t size) {
    if (xSemaphoreTake(spiMutex, portMAX_DELAY)) {
        HAL_SPI_Transmit(&amp;hspi1, data, size, HAL_MAX_DELAY);
        xSemaphoreGive(spiMutex);
    }
}
" 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: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">stm32f4xx_hal.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #5E81AC; font-weight: bold">#</span><span style="color: #81A1C1">include</span><span style="color: #8FBCBB"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">semphr.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">SPI_HandleTypeDef hspi1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #8FBCBB">SemaphoreHandle_t</span><span style="color: #D8DEE9FF"> spiMutex</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">SPI_Write</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">size</span><span style="color: #ECEFF4">)</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: #ECEFF4">(</span><span style="color: #88C0D0">xSemaphoreTake</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">spiMutex</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> portMAX_DELAY</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">HAL_SPI_Transmit</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF">hspi1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> size</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> HAL_MAX_DELAY</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xSemaphoreGive</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">spiMutex</span><span style="color: #ECEFF4">)</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>



<h3 class="wp-block-heading"><strong>Melhor Abordagem</strong></h3>



<ul class="wp-block-list">
<li><strong>I2C</strong>: Como é um barramento compartilhado entre múltiplos dispositivos, <strong>usar um mutex</strong> é essencial para evitar colisões.</li>



<li><strong>SPI</strong>: Em ambientes multitarefa, o <strong>uso de mutex</strong> também é recomendado para evitar que diferentes tarefas tentem acessar o mesmo barramento ao mesmo tempo.</li>



<li><strong>Semáforos</strong> podem ser usados para sincronizar eventos, como a recepção de dados em interrupções.</li>
</ul>



<p class="wp-block-paragraph">Essas práticas garantem que a comunicação com dispositivos externos ocorra de maneira segura e eficiente, sem causar falhas no sistema.</p>



<h2 class="wp-block-heading"><strong>Conclusão</strong></h2>



<p class="wp-block-paragraph">Escolher a técnica correta para o controle de concorrência é essencial para garantir a estabilidade e o desempenho de sistemas multitarefa. Como visto ao longo deste artigo:</p>



<ul class="wp-block-list">
<li><strong>Mutexes</strong> são ideais para garantir exclusão mútua, prevenindo que múltiplas tarefas modifiquem simultaneamente um mesmo recurso compartilhado.</li>



<li><strong>Semáforos</strong> são úteis tanto para controle de múltiplas instâncias de um recurso quanto para sincronização de tarefas.</li>



<li><strong>A suspensão do escalonador</strong> deve ser usada com cuidado, sendo útil apenas em situações críticas onde uma interrupção durante a execução pode causar problemas graves.</li>
</ul>



<p class="wp-block-paragraph">Quando se trata de dispositivos como <strong>I2C</strong> e <strong>SPI</strong>, a escolha de mutexes para proteger o barramento e garantir a integridade da comunicação é a abordagem mais recomendada, enquanto semáforos podem ser úteis para coordenar eventos assíncronos.</p>



<p class="wp-block-paragraph">Entender essas técnicas e aplicá-las corretamente resulta em sistemas mais eficientes, confiáveis e fáceis de manter. O uso adequado de mutexes, semáforos e a suspensão do escalonador garante que aplicações multitarefa operem de maneira fluida, sem impactos negativos na performance do sistema.</p>



<p class="wp-block-paragraph">Com isso, esperamos que este artigo tenha esclarecido as principais diferenças entre essas abordagens e ajudado a tomar decisões mais informadas no desenvolvimento de sistemas embarcados e aplicações multitarefa.</p><p>The post <a href="https://mcu.tec.br/rtos/66-2/"></a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">66</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>
	</channel>
</rss>
