<?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>RTOS - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/categorias/rtos/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Sat, 21 Feb 2026 17:26:31 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</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>RTOS - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Zephyr e Integração Avançada: Interrupções + Soft Timers + Workqueues</title>
		<link>https://mcu.tec.br/geral/zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues</link>
					<comments>https://mcu.tec.br/geral/zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 10 Apr 2026 14:49:36 +0000</pubDate>
				<category><![CDATA[geral]]></category>
		<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura de firmware]]></category>
		<category><![CDATA[boas práticas Zephyr]]></category>
		<category><![CDATA[event driven firmware]]></category>
		<category><![CDATA[firmware escalável]]></category>
		<category><![CDATA[firmware industrial]]></category>
		<category><![CDATA[firmware robusto]]></category>
		<category><![CDATA[interrupções Zephyr]]></category>
		<category><![CDATA[IoT de produção]]></category>
		<category><![CDATA[pipelines de eventos]]></category>
		<category><![CDATA[rtos para iot]]></category>
		<category><![CDATA[sistemas embarcados industriais]]></category>
		<category><![CDATA[soft timers zephyr]]></category>
		<category><![CDATA[workqueues Zephyr]]></category>
		<category><![CDATA[Zephyr k_timer]]></category>
		<category><![CDATA[Zephyr k_work]]></category>
		<category><![CDATA[Zephyr RTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1247</guid>

					<description><![CDATA[<p>O Zephyr RTOS oferece mecanismos poderosos para o desenvolvimento de firmware industrial e IoT de produção. Neste artigo, apresentamos de forma didática e aprofundada como integrar interrupções, soft timers (k_timer) e workqueues (k_work) para projetar pipelines de eventos robustos, escaláveis e previsíveis. O conteúdo explora boas práticas arquiteturais, anti-padrões comuns, controle de prioridade, backpressure e estratégias de recuperação de falhas, com exemplos reais em C. Ideal para engenheiros de sistemas embarcados que desejam evoluir de firmwares reativos simples para arquiteturas industriais confiáveis baseadas em eventos.</p>
<p>The post <a href="https://mcu.tec.br/geral/zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues/">Zephyr e Integração Avançada: Interrupções + Soft Timers + Workqueues</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-f87wq wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-f87wq "><div class="eb-toc-container eb-toc-f87wq  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;2 \u2014 Interrup\u00e7\u00f5es no Zephyr&quot;,&quot;text&quot;:&quot;2 \u2014 Interrup\u00e7\u00f5es no Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;O papel correto das ISRs em pipelines de eventos robustos&quot;,&quot;text&quot;:&quot;O papel correto das ISRs em pipelines de eventos robustos&quot;,&quot;link&quot;:&quot;o-papel-correto-das-isrs-em-pipelines-de-eventos-robustos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 O erro cl\u00e1ssico: ISR como \u201cmini-thread\u201d&quot;,&quot;text&quot;:&quot;2.1 O erro cl\u00e1ssico: ISR como \u201cmini-thread\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 O que uma ISR pode fazer no Zephyr&quot;,&quot;text&quot;:&quot;2.2 O que uma ISR pode fazer no Zephyr&quot;,&quot;link&quot;:&quot;22-o-que-uma-isr-pode-fazer-no-zephyr&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 Exemplo 1 \u2014 Interrup\u00e7\u00e3o de GPIO bem projetada&quot;,&quot;text&quot;:&quot;2.3 Exemplo 1 \u2014 Interrup\u00e7\u00e3o de GPIO bem projetada&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Configura\u00e7\u00e3o do callback de interrup\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Configura\u00e7\u00e3o do callback de interrup\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Inicializa\u00e7\u00e3o do GPIO&quot;,&quot;text&quot;:&quot;Inicializa\u00e7\u00e3o do GPIO&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 A thread consumidora do evento&quot;,&quot;text&quot;:&quot;2.4 A thread consumidora do evento&quot;,&quot;link&quot;:&quot;24-a-thread-consumidora-do-evento&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.5 Regra de ouro para ISRs em firmware industrial&quot;,&quot;text&quot;:&quot;2.5 Regra de ouro para ISRs em firmware industrial&quot;,&quot;link&quot;:&quot;25-regra-de-ouro-para-isrs-em-firmware-industrial&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;3 \u2014 Soft Timers no Zephyr&quot;,&quot;text&quot;:&quot;3 \u2014 Soft Timers no Zephyr&quot;,&quot;link&quot;:&quot;3-soft-timers-no-zephyr&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Tempo como evento, n\u00e3o como delay&quot;,&quot;text&quot;:&quot;Tempo como evento, n\u00e3o como delay&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 O erro comum: k_sleep() como l\u00f3gica&quot;,&quot;text&quot;:&quot;3.1 O erro comum: k_sleep() como l\u00f3gica&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Conceito de Soft Timer no Zephyr&quot;,&quot;text&quot;:&quot;3.2 Conceito de Soft Timer no Zephyr&quot;,&quot;link&quot;:&quot;32-conceito-de-soft-timer-no-zephyr&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Exemplo 2 \u2014 Timer como fonte de eventos&quot;,&quot;text&quot;:&quot;3.3 Exemplo 2 \u2014 Timer como fonte de eventos&quot;,&quot;link&quot;:&quot;33-exemplo-2-timer-como-fonte-de-eventos&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Defini\u00e7\u00e3o do timer&quot;,&quot;text&quot;:&quot;Defini\u00e7\u00e3o do timer&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Inicializa\u00e7\u00e3o do timer&quot;,&quot;text&quot;:&quot;Inicializa\u00e7\u00e3o do timer&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 Consumindo eventos temporais&quot;,&quot;text&quot;:&quot;3.4 Consumindo eventos temporais&quot;,&quot;link&quot;:&quot;34-consumindo-eventos-temporais&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Soft Timer como etapa do pipeline&quot;,&quot;text&quot;:&quot;3.5 Soft Timer como etapa do pipeline&quot;,&quot;link&quot;:&quot;35-soft-timer-como-etapa-do-pipeline&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Regra de ouro dos Soft Timers&quot;,&quot;text&quot;:&quot;3.6 Regra de ouro dos Soft Timers&quot;,&quot;link&quot;:&quot;36-regra-de-ouro-dos-soft-timers&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;4 \u2014 Workqueues no Zephyr&quot;,&quot;text&quot;:&quot;4 \u2014 Workqueues no Zephyr&quot;,&quot;link&quot;:&quot;4-workqueues-no-zephyr&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Processamento desacoplado, escal\u00e1vel e seguro&quot;,&quot;text&quot;:&quot;Processamento desacoplado, escal\u00e1vel e seguro&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 O que \u00e9 uma Workqueue, de fato&quot;,&quot;text&quot;:&quot;4.1 O que \u00e9 uma Workqueue, de fato&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 O erro comum: jogar tudo na system workqueue&quot;,&quot;text&quot;:&quot;4.2 O erro comum: jogar tudo na system workqueue&quot;,&quot;link&quot;:&quot;42-o-erro-comum-jogar-tudo-na-system-workqueue&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Criando uma Workqueue dedicada&quot;,&quot;text&quot;:&quot;4.3 Criando uma Workqueue dedicada&quot;,&quot;link&quot;:&quot;43-criando-uma-workqueue-dedicada&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Defini\u00e7\u00e3o da workqueue&quot;,&quot;text&quot;:&quot;Defini\u00e7\u00e3o da workqueue&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Inicializa\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Inicializa\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Criando um work item&quot;,&quot;text&quot;:&quot;4.4 Criando um work item&quot;,&quot;link&quot;:&quot;44-criando-um-work-item&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Integrando eventos \u2192 workqueues&quot;,&quot;text&quot;:&quot;4.5 Integrando eventos \u2192 workqueues&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;ISR \u2192 Timer \u2192 Workqueue&quot;,&quot;text&quot;:&quot;ISR \u2192 Timer \u2192 Workqueue&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.6 Workqueues como est\u00e1gios de pipeline&quot;,&quot;text&quot;:&quot;4.6 Workqueues como est\u00e1gios de pipeline&quot;,&quot;link&quot;:&quot;eb-table-content-29&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.7 Regra de ouro das Workqueues&quot;,&quot;text&quot;:&quot;4.7 Regra de ouro das Workqueues&quot;,&quot;link&quot;:&quot;47-regra-de-ouro-das-workqueues&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5 \u2014 Desenhando pipelines completos de eventos no Zephyr&quot;,&quot;text&quot;:&quot;5 \u2014 Desenhando pipelines completos de eventos no Zephyr&quot;,&quot;link&quot;:&quot;5-desenhando-pipelines-completos-de-eventos-no-zephyr&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Do evento f\u00edsico ao processamento industrial robusto&quot;,&quot;text&quot;:&quot;Do evento f\u00edsico ao processamento industrial robusto&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 O modelo mental correto: firmware como fluxo de eventos&quot;,&quot;text&quot;:&quot;5.1 O modelo mental correto: firmware como fluxo de eventos&quot;,&quot;link&quot;:&quot;51-o-modelo-mental-correto-firmware-como-fluxo-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Pipeline can\u00f4nico no Zephyr&quot;,&quot;text&quot;:&quot;5.2 Pipeline can\u00f4nico no Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Implementa\u00e7\u00e3o passo a passo&quot;,&quot;text&quot;:&quot;5.3 Implementa\u00e7\u00e3o passo a passo&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;1\ufe0f\u20e3 Interrup\u00e7\u00e3o: entrada do pipeline&quot;,&quot;text&quot;:&quot;1\ufe0f\u20e3 Interrup\u00e7\u00e3o: entrada do pipeline&quot;,&quot;link&quot;:&quot;eb-table-content-36&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;2\ufe0f\u20e3 Soft Timer: debounce e normaliza\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;2\ufe0f\u20e3 Soft Timer: debounce e normaliza\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-37&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;3\ufe0f\u20e3 Workqueue: processamento real&quot;,&quot;text&quot;:&quot;3\ufe0f\u20e3 Workqueue: processamento real&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4\ufe0f\u20e3 Workqueue de comunica\u00e7\u00e3o (opcional, mas comum)&quot;,&quot;text&quot;:&quot;4\ufe0f\u20e3 Workqueue de comunica\u00e7\u00e3o (opcional, mas comum)&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Por que esse pipeline \u00e9 robusto&quot;,&quot;text&quot;:&quot;5.4 Por que esse pipeline \u00e9 robusto&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Anti-padr\u00f5es comuns (e perigosos)&quot;,&quot;text&quot;:&quot;5.5 Anti-padr\u00f5es comuns (e perigosos)&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Regra de ouro do pipeline no Zephyr&quot;,&quot;text&quot;:&quot;5.6 Regra de ouro do pipeline no Zephyr&quot;,&quot;link&quot;:&quot;56-regra-de-ouro-do-pipeline-no-zephyr&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;6 \u2014 Boas pr\u00e1ticas industriais&quot;,&quot;text&quot;:&quot;6 \u2014 Boas pr\u00e1ticas industriais&quot;,&quot;link&quot;:&quot;eb-table-content-43&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Prioridades, backpressure e recupera\u00e7\u00e3o de falhas&quot;,&quot;text&quot;:&quot;Prioridades, backpressure e recupera\u00e7\u00e3o de falhas&quot;,&quot;link&quot;:&quot;eb-table-content-44&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 Prioriza\u00e7\u00e3o correta: tempo \u00e9 um recurso finito&quot;,&quot;text&quot;:&quot;6.1 Prioriza\u00e7\u00e3o correta: tempo \u00e9 um recurso finito&quot;,&quot;link&quot;:&quot;eb-table-content-45&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Regra pr\u00e1tica de prioridade&quot;,&quot;text&quot;:&quot;Regra pr\u00e1tica de prioridade&quot;,&quot;link&quot;:&quot;eb-table-content-46&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Exemplo \u2014 Workqueues com prioridades distintas&quot;,&quot;text&quot;:&quot;6.2 Exemplo \u2014 Workqueues com prioridades distintas&quot;,&quot;link&quot;:&quot;62-exemplo-workqueues-com-prioridades-distintas&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Backpressure: quando eventos chegam r\u00e1pido demais&quot;,&quot;text&quot;:&quot;6.3 Backpressure: quando eventos chegam r\u00e1pido demais&quot;,&quot;link&quot;:&quot;eb-table-content-48&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Estrat\u00e9gias de backpressure no Zephyr&quot;,&quot;text&quot;:&quot;Estrat\u00e9gias de backpressure no Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-49&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 Exemplo \u2014 Limitando eventos com k_msgq&quot;,&quot;text&quot;:&quot;6.4 Exemplo \u2014 Limitando eventos com k_msgq&quot;,&quot;link&quot;:&quot;64-exemplo-limitando-eventos-com-k_msgq&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.5 Eventos colaps\u00e1veis (coalescing)&quot;,&quot;text&quot;:&quot;6.5 Eventos colaps\u00e1veis (coalescing)&quot;,&quot;link&quot;:&quot;eb-table-content-51&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.6 Recupera\u00e7\u00e3o de falhas no pipeline&quot;,&quot;text&quot;:&quot;6.6 Recupera\u00e7\u00e3o de falhas no pipeline&quot;,&quot;link&quot;:&quot;eb-table-content-52&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Exemplo \u2014 Timeout l\u00f3gico com timer&quot;,&quot;text&quot;:&quot;Exemplo \u2014 Timeout l\u00f3gico com timer&quot;,&quot;link&quot;:&quot;eb-table-content-53&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.7 Checklist industrial de robustez&quot;,&quot;text&quot;:&quot;6.7 Checklist industrial de robustez&quot;,&quot;link&quot;:&quot;67-checklist-industrial-de-robustez&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;7 \u2014 Estudo de caso completo&quot;,&quot;text&quot;:&quot;7 \u2014 Estudo de caso completo&quot;,&quot;link&quot;:&quot;7-estudo-de-caso-completo&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Pipeline Zephyr em um dispositivo IoT industrial (sensor \u2192 processamento \u2192 nuvem)&quot;,&quot;text&quot;:&quot;Pipeline Zephyr em um dispositivo IoT industrial (sensor \u2192 processamento \u2192 nuvem)&quot;,&quot;link&quot;:&quot;eb-table-content-56&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.1 Cen\u00e1rio do sistema&quot;,&quot;text&quot;:&quot;7.1 Cen\u00e1rio do sistema&quot;,&quot;link&quot;:&quot;eb-table-content-57&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.2 Arquitetura do pipeline&quot;,&quot;text&quot;:&quot;7.2 Arquitetura do pipeline&quot;,&quot;link&quot;:&quot;72-arquitetura-do-pipeline&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.3 Est\u00e1gio 1 \u2014 ISR (evento f\u00edsico)&quot;,&quot;text&quot;:&quot;7.3 Est\u00e1gio 1 \u2014 ISR (evento f\u00edsico)&quot;,&quot;link&quot;:&quot;eb-table-content-59&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.4 Est\u00e1gio 2 \u2014 Soft Timer (normaliza\u00e7\u00e3o temporal)&quot;,&quot;text&quot;:&quot;7.4 Est\u00e1gio 2 \u2014 Soft Timer (normaliza\u00e7\u00e3o temporal)&quot;,&quot;link&quot;:&quot;eb-table-content-60&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.5 Est\u00e1gio 3 \u2014 Workqueue de aquisi\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;7.5 Est\u00e1gio 3 \u2014 Workqueue de aquisi\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-61&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.6 Est\u00e1gio 4 \u2014 Workqueue de processamento&quot;,&quot;text&quot;:&quot;7.6 Est\u00e1gio 4 \u2014 Workqueue de processamento&quot;,&quot;link&quot;:&quot;eb-table-content-62&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.7 Est\u00e1gio 5 \u2014 Workqueue de comunica\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;7.7 Est\u00e1gio 5 \u2014 Workqueue de comunica\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-63&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.8 Controle de carga (backpressure)&quot;,&quot;text&quot;:&quot;7.8 Controle de carga (backpressure)&quot;,&quot;link&quot;:&quot;78-controle-de-carga-backpressure&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.9 Recupera\u00e7\u00e3o e robustez&quot;,&quot;text&quot;:&quot;7.9 Recupera\u00e7\u00e3o e robustez&quot;,&quot;link&quot;:&quot;eb-table-content-65&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.10 O que esse estudo de caso demonstra&quot;,&quot;text&quot;:&quot;7.10 O que esse estudo de caso demonstra&quot;,&quot;link&quot;:&quot;710-o-que-esse-estudo-de-caso-demonstra&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;8 \u2014 Conclus\u00e3o&quot;,&quot;text&quot;:&quot;8 \u2014 Conclus\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-67&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00f5es mentais e checklist para firmware industrial com Zephyr&quot;,&quot;text&quot;:&quot;Padr\u00f5es mentais e checklist para firmware industrial com Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-68&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.1 O modelo mental correto (o que levar deste artigo)&quot;,&quot;text&quot;:&quot;8.1 O modelo mental correto (o que levar deste artigo)&quot;,&quot;link&quot;:&quot;81-o-modelo-mental-correto-o-que-levar-deste-artigo&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.2 Anti-padr\u00f5es finais a evitar&quot;,&quot;text&quot;:&quot;8.2 Anti-padr\u00f5es finais a evitar&quot;,&quot;link&quot;:&quot;eb-table-content-70&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.3 Checklist pr\u00e1tico de revis\u00e3o arquitetural&quot;,&quot;text&quot;:&quot;8.3 Checklist pr\u00e1tico de revis\u00e3o arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-71&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.4 Onde esse padr\u00e3o \u00e9 usado na pr\u00e1tica&quot;,&quot;text&quot;:&quot;8.4 Onde esse padr\u00e3o \u00e9 usado na pr\u00e1tica&quot;,&quot;link&quot;:&quot;eb-table-content-72&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.5 Encerramento&quot;,&quot;text&quot;:&quot;8.5 Encerramento&quot;,&quot;link&quot;:&quot;85-encerramento&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;2 \u2014 Interrup\u00e7\u00f5es no Zephyr&quot;,&quot;value&quot;:&quot;2-interrup\u00e7\u00f5es-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O papel correto das ISRs em pipelines de eventos robustos&quot;,&quot;value&quot;:&quot;o-papel-correto-das-isrs-em-pipelines-de-eventos-robustos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 O erro cl\u00e1ssico: ISR como \u201cmini-thread\u201d&quot;,&quot;value&quot;:&quot;21-o-erro-cl\u00e1ssico-isr-como-mini-thread&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 O que uma ISR pode fazer no Zephyr&quot;,&quot;value&quot;:&quot;22-o-que-uma-isr-pode-fazer-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 Exemplo 1 \u2014 Interrup\u00e7\u00e3o de GPIO bem projetada&quot;,&quot;value&quot;:&quot;23-exemplo-1-interrup\u00e7\u00e3o-de-gpio-bem-projetada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Configura\u00e7\u00e3o do callback de interrup\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;configura\u00e7\u00e3o-do-callback-de-interrup\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Inicializa\u00e7\u00e3o do GPIO&quot;,&quot;value&quot;:&quot;inicializa\u00e7\u00e3o-do-gpio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 A thread consumidora do evento&quot;,&quot;value&quot;:&quot;24-a-thread-consumidora-do-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.5 Regra de ouro para ISRs em firmware industrial&quot;,&quot;value&quot;:&quot;25-regra-de-ouro-para-isrs-em-firmware-industrial&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3 \u2014 Soft Timers no Zephyr&quot;,&quot;value&quot;:&quot;3-soft-timers-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Tempo como evento, n\u00e3o como delay&quot;,&quot;value&quot;:&quot;tempo-como-evento-n\u00e3o-como-delay&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 O erro comum: k_sleep() como l\u00f3gica&quot;,&quot;value&quot;:&quot;31-o-erro-comum-k_sleep-como-l\u00f3gica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Conceito de Soft Timer no Zephyr&quot;,&quot;value&quot;:&quot;32-conceito-de-soft-timer-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Exemplo 2 \u2014 Timer como fonte de eventos&quot;,&quot;value&quot;:&quot;33-exemplo-2-timer-como-fonte-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Defini\u00e7\u00e3o do timer&quot;,&quot;value&quot;:&quot;defini\u00e7\u00e3o-do-timer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Inicializa\u00e7\u00e3o do timer&quot;,&quot;value&quot;:&quot;inicializa\u00e7\u00e3o-do-timer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 Consumindo eventos temporais&quot;,&quot;value&quot;:&quot;34-consumindo-eventos-temporais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Soft Timer como etapa do pipeline&quot;,&quot;value&quot;:&quot;35-soft-timer-como-etapa-do-pipeline&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Regra de ouro dos Soft Timers&quot;,&quot;value&quot;:&quot;36-regra-de-ouro-dos-soft-timers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4 \u2014 Workqueues no Zephyr&quot;,&quot;value&quot;:&quot;4-workqueues-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Processamento desacoplado, escal\u00e1vel e seguro&quot;,&quot;value&quot;:&quot;processamento-desacoplado-escal\u00e1vel-e-seguro&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 O que \u00e9 uma Workqueue, de fato&quot;,&quot;value&quot;:&quot;41-o-que-\u00e9-uma-workqueue-de-fato&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 O erro comum: jogar tudo na system workqueue&quot;,&quot;value&quot;:&quot;42-o-erro-comum-jogar-tudo-na-system-workqueue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Criando uma Workqueue dedicada&quot;,&quot;value&quot;:&quot;43-criando-uma-workqueue-dedicada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Defini\u00e7\u00e3o da workqueue&quot;,&quot;value&quot;:&quot;defini\u00e7\u00e3o-da-workqueue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Inicializa\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;inicializa\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Criando um work item&quot;,&quot;value&quot;:&quot;44-criando-um-work-item&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Integrando eventos \u2192 workqueues&quot;,&quot;value&quot;:&quot;45-integrando-eventos-\u2192-workqueues&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;ISR \u2192 Timer \u2192 Workqueue&quot;,&quot;value&quot;:&quot;isr-\u2192-timer-\u2192-workqueue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.6 Workqueues como est\u00e1gios de pipeline&quot;,&quot;value&quot;:&quot;46-workqueues-como-est\u00e1gios-de-pipeline&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.7 Regra de ouro das Workqueues&quot;,&quot;value&quot;:&quot;47-regra-de-ouro-das-workqueues&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5 \u2014 Desenhando pipelines completos de eventos no Zephyr&quot;,&quot;value&quot;:&quot;5-desenhando-pipelines-completos-de-eventos-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Do evento f\u00edsico ao processamento industrial robusto&quot;,&quot;value&quot;:&quot;do-evento-f\u00edsico-ao-processamento-industrial-robusto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 O modelo mental correto: firmware como fluxo de eventos&quot;,&quot;value&quot;:&quot;51-o-modelo-mental-correto-firmware-como-fluxo-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Pipeline can\u00f4nico no Zephyr&quot;,&quot;value&quot;:&quot;52-pipeline-can\u00f4nico-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Implementa\u00e7\u00e3o passo a passo&quot;,&quot;value&quot;:&quot;53-implementa\u00e7\u00e3o-passo-a-passo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1\ufe0f\u20e3 Interrup\u00e7\u00e3o: entrada do pipeline&quot;,&quot;value&quot;:&quot;1\ufe0f\u20e3-interrup\u00e7\u00e3o-entrada-do-pipeline&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2\ufe0f\u20e3 Soft Timer: debounce e normaliza\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;2\ufe0f\u20e3-soft-timer-debounce-e-normaliza\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3\ufe0f\u20e3 Workqueue: processamento real&quot;,&quot;value&quot;:&quot;3\ufe0f\u20e3-workqueue-processamento-real&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4\ufe0f\u20e3 Workqueue de comunica\u00e7\u00e3o (opcional, mas comum)&quot;,&quot;value&quot;:&quot;4\ufe0f\u20e3-workqueue-de-comunica\u00e7\u00e3o-opcional-mas-comum&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Por que esse pipeline \u00e9 robusto&quot;,&quot;value&quot;:&quot;54-por-que-esse-pipeline-\u00e9-robusto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Anti-padr\u00f5es comuns (e perigosos)&quot;,&quot;value&quot;:&quot;55-anti-padr\u00f5es-comuns-e-perigosos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Regra de ouro do pipeline no Zephyr&quot;,&quot;value&quot;:&quot;56-regra-de-ouro-do-pipeline-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6 \u2014 Boas pr\u00e1ticas industriais&quot;,&quot;value&quot;:&quot;6-boas-pr\u00e1ticas-industriais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Prioridades, backpressure e recupera\u00e7\u00e3o de falhas&quot;,&quot;value&quot;:&quot;prioridades-backpressure-e-recupera\u00e7\u00e3o-de-falhas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 Prioriza\u00e7\u00e3o correta: tempo \u00e9 um recurso finito&quot;,&quot;value&quot;:&quot;61-prioriza\u00e7\u00e3o-correta-tempo-\u00e9-um-recurso-finito&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Regra pr\u00e1tica de prioridade&quot;,&quot;value&quot;:&quot;regra-pr\u00e1tica-de-prioridade&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Exemplo \u2014 Workqueues com prioridades distintas&quot;,&quot;value&quot;:&quot;62-exemplo-workqueues-com-prioridades-distintas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Backpressure: quando eventos chegam r\u00e1pido demais&quot;,&quot;value&quot;:&quot;63-backpressure-quando-eventos-chegam-r\u00e1pido-demais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Estrat\u00e9gias de backpressure no Zephyr&quot;,&quot;value&quot;:&quot;estrat\u00e9gias-de-backpressure-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 Exemplo \u2014 Limitando eventos com k_msgq&quot;,&quot;value&quot;:&quot;64-exemplo-limitando-eventos-com-k_msgq&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.5 Eventos colaps\u00e1veis (coalescing)&quot;,&quot;value&quot;:&quot;65-eventos-colaps\u00e1veis-coalescing&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.6 Recupera\u00e7\u00e3o de falhas no pipeline&quot;,&quot;value&quot;:&quot;66-recupera\u00e7\u00e3o-de-falhas-no-pipeline&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo \u2014 Timeout l\u00f3gico com timer&quot;,&quot;value&quot;:&quot;exemplo-timeout-l\u00f3gico-com-timer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.7 Checklist industrial de robustez&quot;,&quot;value&quot;:&quot;67-checklist-industrial-de-robustez&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7 \u2014 Estudo de caso completo&quot;,&quot;value&quot;:&quot;7-estudo-de-caso-completo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Pipeline Zephyr em um dispositivo IoT industrial (sensor \u2192 processamento \u2192 nuvem)&quot;,&quot;value&quot;:&quot;pipeline-zephyr-em-um-dispositivo-iot-industrial-sensor-\u2192-processamento-\u2192-nuvem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.1 Cen\u00e1rio do sistema&quot;,&quot;value&quot;:&quot;71-cen\u00e1rio-do-sistema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.2 Arquitetura do pipeline&quot;,&quot;value&quot;:&quot;72-arquitetura-do-pipeline&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.3 Est\u00e1gio 1 \u2014 ISR (evento f\u00edsico)&quot;,&quot;value&quot;:&quot;73-est\u00e1gio-1-isr-evento-f\u00edsico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.4 Est\u00e1gio 2 \u2014 Soft Timer (normaliza\u00e7\u00e3o temporal)&quot;,&quot;value&quot;:&quot;74-est\u00e1gio-2-soft-timer-normaliza\u00e7\u00e3o-temporal&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.5 Est\u00e1gio 3 \u2014 Workqueue de aquisi\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;75-est\u00e1gio-3-workqueue-de-aquisi\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.6 Est\u00e1gio 4 \u2014 Workqueue de processamento&quot;,&quot;value&quot;:&quot;76-est\u00e1gio-4-workqueue-de-processamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.7 Est\u00e1gio 5 \u2014 Workqueue de comunica\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;77-est\u00e1gio-5-workqueue-de-comunica\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.8 Controle de carga (backpressure)&quot;,&quot;value&quot;:&quot;78-controle-de-carga-backpressure&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.9 Recupera\u00e7\u00e3o e robustez&quot;,&quot;value&quot;:&quot;79-recupera\u00e7\u00e3o-e-robustez&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.10 O que esse estudo de caso demonstra&quot;,&quot;value&quot;:&quot;710-o-que-esse-estudo-de-caso-demonstra&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8 \u2014 Conclus\u00e3o&quot;,&quot;value&quot;:&quot;8-conclus\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es mentais e checklist para firmware industrial com Zephyr&quot;,&quot;value&quot;:&quot;padr\u00f5es-mentais-e-checklist-para-firmware-industrial-com-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.1 O modelo mental correto (o que levar deste artigo)&quot;,&quot;value&quot;:&quot;81-o-modelo-mental-correto-o-que-levar-deste-artigo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.2 Anti-padr\u00f5es finais a evitar&quot;,&quot;value&quot;:&quot;82-anti-padr\u00f5es-finais-a-evitar&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.3 Checklist pr\u00e1tico de revis\u00e3o arquitetural&quot;,&quot;value&quot;:&quot;83-checklist-pr\u00e1tico-de-revis\u00e3o-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.4 Onde esse padr\u00e3o \u00e9 usado na pr\u00e1tica&quot;,&quot;value&quot;:&quot;84-onde-esse-padr\u00e3o-\u00e9-usado-na-pr\u00e1tica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.5 Encerramento&quot;,&quot;value&quot;:&quot;85-encerramento&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">2 — Interrupções no Zephyr</a><ul class='eb-toc__list'><li><a href="#o-papel-correto-das-isrs-em-pipelines-de-eventos-robustos">O papel correto das ISRs em pipelines de eventos robustos</a><li><a href="#eb-table-content-2">2.1 O erro clássico: ISR como “mini-thread”</a><li><a href="#22-o-que-uma-isr-pode-fazer-no-zephyr">2.2 O que uma ISR pode fazer no Zephyr</a><li><a href="#eb-table-content-4">2.3 Exemplo 1 — Interrupção de GPIO bem projetada</a><ul class='eb-toc__list'><li><a href="#eb-table-content-5">Configuração do callback de interrupção</a><li><a href="#eb-table-content-6">Inicialização do GPIO</a></li></ul><li><a href="#24-a-thread-consumidora-do-evento">2.4 A thread consumidora do evento</a><li><a href="#25-regra-de-ouro-para-isrs-em-firmware-industrial">2.5 Regra de ouro para ISRs em firmware industrial</a></li></ul><li><a href="#3-soft-timers-no-zephyr">3 — Soft Timers no Zephyr</a><ul class='eb-toc__list'><li><a href="#eb-table-content-10">Tempo como evento, não como delay</a><li><a href="#eb-table-content-11">3.1 O erro comum: k_sleep() como lógica</a><li><a href="#32-conceito-de-soft-timer-no-zephyr">3.2 Conceito de Soft Timer no Zephyr</a><li><a href="#33-exemplo-2-timer-como-fonte-de-eventos">3.3 Exemplo 2 — Timer como fonte de eventos</a><ul class='eb-toc__list'><li><a href="#eb-table-content-14">Definição do timer</a><li><a href="#eb-table-content-15">Inicialização do timer</a></li></ul><li><a href="#34-consumindo-eventos-temporais">3.4 Consumindo eventos temporais</a><li><a href="#35-soft-timer-como-etapa-do-pipeline">3.5 Soft Timer como etapa do pipeline</a><li><a href="#36-regra-de-ouro-dos-soft-timers">3.6 Regra de ouro dos Soft Timers</a></li></ul><li><a href="#4-workqueues-no-zephyr">4 — Workqueues no Zephyr</a><ul class='eb-toc__list'><li><a href="#eb-table-content-20">Processamento desacoplado, escalável e seguro</a><li><a href="#eb-table-content-21">4.1 O que é uma Workqueue, de fato</a><li><a href="#42-o-erro-comum-jogar-tudo-na-system-workqueue">4.2 O erro comum: jogar tudo na system workqueue</a><li><a href="#43-criando-uma-workqueue-dedicada">4.3 Criando uma Workqueue dedicada</a><ul class='eb-toc__list'><li><a href="#eb-table-content-24">Definição da workqueue</a><li><a href="#eb-table-content-25">Inicialização</a></li></ul><li><a href="#44-criando-um-work-item">4.4 Criando um work item</a><li><a href="#eb-table-content-27">4.5 Integrando eventos → workqueues</a><ul class='eb-toc__list'><li><a href="#eb-table-content-28">ISR → Timer → Workqueue</a></li></ul><li><a href="#eb-table-content-29">4.6 Workqueues como estágios de pipeline</a><li><a href="#47-regra-de-ouro-das-workqueues">4.7 Regra de ouro das Workqueues</a></li></ul><li><a href="#5-desenhando-pipelines-completos-de-eventos-no-zephyr">5 — Desenhando pipelines completos de eventos no Zephyr</a><ul class='eb-toc__list'><li><a href="#eb-table-content-32">Do evento físico ao processamento industrial robusto</a><li><a href="#51-o-modelo-mental-correto-firmware-como-fluxo-de-eventos">5.1 O modelo mental correto: firmware como fluxo de eventos</a><li><a href="#eb-table-content-34">5.2 Pipeline canônico no Zephyr</a><li><a href="#eb-table-content-35">5.3 Implementação passo a passo</a><ul class='eb-toc__list'><li><a href="#eb-table-content-36">1&#xfe0f;&#x20e3; Interrupção: entrada do pipeline</a><li><a href="#eb-table-content-37">2&#xfe0f;&#x20e3; Soft Timer: debounce e normalização</a><li><a href="#eb-table-content-38">3&#xfe0f;&#x20e3; Workqueue: processamento real</a><li><a href="#eb-table-content-39">4&#xfe0f;&#x20e3; Workqueue de comunicação (opcional, mas comum)</a></li></ul><li><a href="#eb-table-content-40">5.4 Por que esse pipeline é robusto</a><li><a href="#eb-table-content-41">5.5 Anti-padrões comuns (e perigosos)</a><li><a href="#56-regra-de-ouro-do-pipeline-no-zephyr">5.6 Regra de ouro do pipeline no Zephyr</a></li></ul><li><a href="#eb-table-content-43">6 — Boas práticas industriais</a><ul class='eb-toc__list'><li><a href="#eb-table-content-44">Prioridades, backpressure e recuperação de falhas</a><li><a href="#eb-table-content-45">6.1 Priorização correta: tempo é um recurso finito</a><ul class='eb-toc__list'><li><a href="#eb-table-content-46">Regra prática de prioridade</a></li></ul><li><a href="#62-exemplo-workqueues-com-prioridades-distintas">6.2 Exemplo — Workqueues com prioridades distintas</a><li><a href="#eb-table-content-48">6.3 Backpressure: quando eventos chegam rápido demais</a><ul class='eb-toc__list'><li><a href="#eb-table-content-49">Estratégias de backpressure no Zephyr</a></li></ul><li><a href="#64-exemplo-limitando-eventos-com-k_msgq">6.4 Exemplo — Limitando eventos com k_msgq</a><li><a href="#eb-table-content-51">6.5 Eventos colapsáveis (coalescing)</a><li><a href="#eb-table-content-52">6.6 Recuperação de falhas no pipeline</a><ul class='eb-toc__list'><li><a href="#eb-table-content-53">Exemplo — Timeout lógico com timer</a></li></ul><li><a href="#67-checklist-industrial-de-robustez">6.7 Checklist industrial de robustez</a></li></ul><li><a href="#7-estudo-de-caso-completo">7 — Estudo de caso completo</a><ul class='eb-toc__list'><li><a href="#eb-table-content-56">Pipeline Zephyr em um dispositivo IoT industrial (sensor → processamento → nuvem)</a><li><a href="#eb-table-content-57">7.1 Cenário do sistema</a><li><a href="#72-arquitetura-do-pipeline">7.2 Arquitetura do pipeline</a><li><a href="#eb-table-content-59">7.3 Estágio 1 — ISR (evento físico)</a><li><a href="#eb-table-content-60">7.4 Estágio 2 — Soft Timer (normalização temporal)</a><li><a href="#eb-table-content-61">7.5 Estágio 3 — Workqueue de aquisição</a><li><a href="#eb-table-content-62">7.6 Estágio 4 — Workqueue de processamento</a><li><a href="#eb-table-content-63">7.7 Estágio 5 — Workqueue de comunicação</a><li><a href="#78-controle-de-carga-backpressure">7.8 Controle de carga (backpressure)</a><li><a href="#eb-table-content-65">7.9 Recuperação e robustez</a><li><a href="#710-o-que-esse-estudo-de-caso-demonstra">7.10 O que esse estudo de caso demonstra</a></li></ul><li><a href="#eb-table-content-67">8 — Conclusão</a><ul class='eb-toc__list'><li><a href="#eb-table-content-68">Padrões mentais e checklist para firmware industrial com Zephyr</a><li><a href="#81-o-modelo-mental-correto-o-que-levar-deste-artigo">8.1 O modelo mental correto (o que levar deste artigo)</a><li><a href="#eb-table-content-70">8.2 Anti-padrões finais a evitar</a><li><a href="#eb-table-content-71">8.3 Checklist prático de revisão arquitetural</a><li><a href="#eb-table-content-72">8.4 Onde esse padrão é usado na prática</a><li><a href="#85-encerramento">8.5 Encerramento</a></li></ul></ul></div></div></div></div></div>


<p>Em firmware <strong>industrial</strong> e <strong>IoT de produção</strong>, o problema raramente é “como ler um sensor” ou “como reagir a uma interrupção”. O desafio real está em <strong>como transformar eventos assíncronos e imprevisíveis</strong> (interrupções de hardware, timeouts, pacotes de rede, watchdogs) em <strong>fluxos determinísticos, observáveis e recuperáveis</strong> — sem violar latência, sem bloquear ISRs, sem explodir prioridade e sem criar acoplamentos frágeis entre camadas.</p>



<p>O <strong>Zephyr RTOS</strong> se destaca exatamente por oferecer <strong>primitivas complementares</strong> — <em>Interrupções</em>, <em>Soft Timers</em> (<code>k_timer</code>) e <em>Workqueues</em> (<code>k_work</code>) — que, quando <strong>combinadas corretamente</strong>, permitem desenhar <strong>pipelines de eventos robustos</strong>, usados em produtos reais: gateways industriais, sensores remotos, equipamentos médicos, automação predial e dispositivos conectados operando por anos no campo.</p>



<p>Este artigo não trata essas primitivas de forma isolada. O foco é <strong>arquitetural</strong>:<br>como <strong>compor</strong> essas ferramentas para criar <strong>fluxos de processamento desacoplados</strong>, previsíveis e testáveis, respeitando as regras fundamentais de sistemas embarcados modernos:</p>



<ul class="wp-block-list">
<li><strong>ISR mínima</strong>: interrupção apenas sinaliza, nunca processa.</li>



<li><strong>Tempo como evento</strong>: temporização explícita, não “sleep espalhado”.</li>



<li><strong>Processamento fora de ISR</strong>: trabalho pesado sempre em contexto de thread.</li>



<li><strong>Backpressure e ordenação</strong>: eventos fluem por etapas bem definidas.</li>



<li><strong>Escalabilidade</strong>: o desenho deve sobreviver ao crescimento do sistema.</li>
</ul>



<p>Ao longo das próximas seções, vamos evoluir de um <strong>modelo mental</strong> até <strong>códigos concretos em C</strong>, mostrando:</p>



<ol class="wp-block-list">
<li>O papel correto de <strong>Interrupções</strong> no Zephyr.</li>



<li>Como <strong>Soft Timers</strong> viram fontes de eventos temporais confiáveis.</li>



<li>Como <strong>Workqueues</strong> funcionam como estágios de processamento.</li>



<li>Como integrar tudo isso em <strong>pipelines de eventos industriais</strong>, com exemplos reais de firmware.</li>
</ol>



<p>A ideia é que, ao final, você não apenas “saiba usar” essas APIs, mas <strong>consiga enxergar a arquitetura</strong> por trás de um firmware profissional — aquele que não depende de sorte, nem de atrasos mágicos, nem de lógica escondida em ISR.</p><p>The post <a href="https://mcu.tec.br/geral/zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues/">Zephyr e Integração Avançada: Interrupções + Soft Timers + Workqueues</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/geral/zephyr-e-integracao-avancada-interrupcoes-soft-timers-workqueues/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1247</post-id>	</item>
		<item>
		<title>Interrupções e Soft Timers no Zephyr OS</title>
		<link>https://mcu.tec.br/rtos/interrupcoes-e-soft-timers-no-zephyr-os/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=interrupcoes-e-soft-timers-no-zephyr-os</link>
					<comments>https://mcu.tec.br/rtos/interrupcoes-e-soft-timers-no-zephyr-os/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 03 Apr 2026 14:04:49 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[firmware em tempo real]]></category>
		<category><![CDATA[gpio interrupt zephyr]]></category>
		<category><![CDATA[interrupções no zephyr]]></category>
		<category><![CDATA[isr zephyr]]></category>
		<category><![CDATA[k_timer zephyr]]></category>
		<category><![CDATA[programação embarcada com zephyr]]></category>
		<category><![CDATA[rtos para iot]]></category>
		<category><![CDATA[sistemas embarcados modernos]]></category>
		<category><![CDATA[soft timers zephyr]]></category>
		<category><![CDATA[zephyr kernel]]></category>
		<category><![CDATA[Zephyr OS]]></category>
		<category><![CDATA[Zephyr RTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1244</guid>

					<description><![CDATA[<p>Este artigo apresenta um guia técnico e didático sobre o uso de interrupções de hardware e soft timers no Zephyr OS, um sistema operacional de tempo real amplamente utilizado em projetos de IoT e sistemas embarcados modernos. O conteúdo explora a filosofia do Zephyr para tratamento de eventos assíncronos, detalhando como funcionam as ISRs (Interrupt Service Routines), a integração com GPIOs, a sinalização correta de threads e o uso seguro de semáforos. Em seguida, o artigo aprofunda o uso de soft timers (k_timer), explicando sua arquitetura interna, diferenças em relação aos timers de hardware, modos de operação periódicos e one-shot, além de padrões recomendados para firmware escalável. Com exemplos práticos em C, o texto mostra como combinar interrupções, timers e threads para criar sistemas previsíveis, portáveis e robustos, alinhados às boas práticas de desenvolvimento profissional com Zephyr RTOS.</p>
<p>The post <a href="https://mcu.tec.br/rtos/interrupcoes-e-soft-timers-no-zephyr-os/">Interrupções e Soft Timers no Zephyr OS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Interrupções e Soft Timers no Zephyr OS: Guia Completo para Firmware em RTOS</p>



<p><strong>Frase-chave foco</strong></p>


<div class="root-eb-toc-iu744 wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-iu744 "><div class="eb-toc-container eb-toc-iu744  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;1 \u2013 Introdu\u00e7\u00e3o: o papel de Interrup\u00e7\u00f5es e Soft Timers em um RTOS moderno&quot;,&quot;text&quot;:&quot;1 \u2013 Introdu\u00e7\u00e3o: o papel de Interrup\u00e7\u00f5es e Soft Timers em um RTOS moderno&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2 \u2013 Modelo de Interrup\u00e7\u00f5es no Zephyr: conceitos fundamentais&quot;,&quot;text&quot;:&quot;2 \u2013 Modelo de Interrup\u00e7\u00f5es no Zephyr: conceitos fundamentais&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;O que \u00e9 uma ISR no Zephyr?&quot;,&quot;text&quot;:&quot;O que \u00e9 uma ISR no Zephyr?&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3 \u2013 Conectando uma interrup\u00e7\u00e3o no Zephyr (exemplo com GPIO)&quot;,&quot;text&quot;:&quot;3 \u2013 Conectando uma interrup\u00e7\u00e3o no Zephyr (exemplo com GPIO)&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Passo 1 \u2013 Defini\u00e7\u00e3o no Devicetree (conceito)&quot;,&quot;text&quot;:&quot;Passo 1 \u2013 Defini\u00e7\u00e3o no Devicetree (conceito)&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Passo 2 \u2013 Estrutura de callback de GPIO&quot;,&quot;text&quot;:&quot;Passo 2 \u2013 Estrutura de callback de GPIO&quot;,&quot;link&quot;:&quot;passo-2-estrutura-de-callback-de-gpio&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Passo 3 \u2013 Implementa\u00e7\u00e3o da ISR&quot;,&quot;text&quot;:&quot;Passo 3 \u2013 Implementa\u00e7\u00e3o da ISR&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;Passo 4 \u2013 Configura\u00e7\u00e3o do GPIO e da interrup\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Passo 4 \u2013 Configura\u00e7\u00e3o do GPIO e da interrup\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4 \u2013 Arquitetura correta: ISR + sinaliza\u00e7\u00e3o de thread&quot;,&quot;text&quot;:&quot;4 \u2013 Arquitetura correta: ISR + sinaliza\u00e7\u00e3o de thread&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;1 \u2013 Introdu\u00e7\u00e3o: o papel de Interrup\u00e7\u00f5es e Soft Timers em um RTOS moderno&quot;,&quot;value&quot;:&quot;1-introdu\u00e7\u00e3o-o-papel-de-interrup\u00e7\u00f5es-e-soft-timers-em-um-rtos-moderno&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2 \u2013 Modelo de Interrup\u00e7\u00f5es no Zephyr: conceitos fundamentais&quot;,&quot;value&quot;:&quot;2-modelo-de-interrup\u00e7\u00f5es-no-zephyr-conceitos-fundamentais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que \u00e9 uma ISR no Zephyr?&quot;,&quot;value&quot;:&quot;o-que-\u00e9-uma-isr-no-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3 \u2013 Conectando uma interrup\u00e7\u00e3o no Zephyr (exemplo com GPIO)&quot;,&quot;value&quot;:&quot;3-conectando-uma-interrup\u00e7\u00e3o-no-zephyr-exemplo-com-gpio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Passo 1 \u2013 Defini\u00e7\u00e3o no Devicetree (conceito)&quot;,&quot;value&quot;:&quot;passo-1-defini\u00e7\u00e3o-no-devicetree-conceito&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Passo 2 \u2013 Estrutura de callback de GPIO&quot;,&quot;value&quot;:&quot;passo-2-estrutura-de-callback-de-gpio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Passo 3 \u2013 Implementa\u00e7\u00e3o da ISR&quot;,&quot;value&quot;:&quot;passo-3-implementa\u00e7\u00e3o-da-isr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Passo 4 \u2013 Configura\u00e7\u00e3o do GPIO e da interrup\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;passo-4-configura\u00e7\u00e3o-do-gpio-e-da-interrup\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4 \u2013 Arquitetura correta: ISR + sinaliza\u00e7\u00e3o de thread&quot;,&quot;value&quot;:&quot;4-arquitetura-correta-isr-sinaliza\u00e7\u00e3o-de-thread&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">1 – Introdução: o papel de Interrupções e Soft Timers em um RTOS moderno</a><li><a href="#eb-table-content-1">2 – Modelo de Interrupções no Zephyr: conceitos fundamentais</a><ul class='eb-toc__list'><li><a href="#eb-table-content-2">O que é uma ISR no Zephyr?</a></li></ul><li><a href="#eb-table-content-3">3 – Conectando uma interrupção no Zephyr (exemplo com GPIO)</a><ul class='eb-toc__list'><li><a href="#eb-table-content-4">Passo 1 – Definição no Devicetree (conceito)</a><li><a href="#passo-2-estrutura-de-callback-de-gpio">Passo 2 – Estrutura de callback de GPIO</a><li><a href="#eb-table-content-6">Passo 3 – Implementação da ISR</a><li><a href="#eb-table-content-7">Passo 4 – Configuração do GPIO e da interrupção</a></li></ul><li><a href="#eb-table-content-8">4 – Arquitetura correta: ISR + sinalização de thread</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading"><strong>1 – Introdução: o papel de Interrupções e Soft Timers em um RTOS moderno</strong></h3>



<p>Em sistemas embarcados modernos, especialmente aqueles baseados em um <strong>RTOS (Real-Time Operating System)</strong> como o <strong>Zephyr OS</strong>, a forma como lidamos com eventos assíncronos define diretamente a robustez, a previsibilidade temporal e a escalabilidade do firmware. Dois mecanismos são absolutamente centrais nesse contexto: <strong>interrupções de hardware</strong> e <strong>soft timers</strong>. Embora ambos sejam usados para reagir a eventos no tempo ou no mundo físico, eles possuem naturezas, custos e implicações arquiteturais bastante distintas.</p>



<p>As <strong>interrupções</strong> permitem que o hardware “interrompa” a execução normal da CPU para tratar eventos críticos e de baixa latência, como mudanças em GPIOs, chegada de dados em periféricos ou estouros de contadores. Já os <strong>soft timers</strong> do Zephyr são abstrações de alto nível baseadas no kernel, que permitem executar callbacks temporizados sem recorrer a timers de hardware dedicados ou lógica de polling. Essa separação clara entre o que é <em>tempo crítico</em> e o que é <em>tempo gerenciado pelo kernel</em> é uma das grandes virtudes do Zephyr.</p>



<p>Um erro comum de quem vem de arquiteturas bare-metal ou de RTOS mais simples é tentar resolver tudo com interrupções. No Zephyr, isso é um <strong>anti-padrão arquitetural</strong>. O sistema foi projetado para que interrupções sejam <strong>curtas, determinísticas e não bloqueantes</strong>, delegando o processamento mais pesado para threads, workqueues ou timers. Entender essa filosofia é essencial para escrever firmware escalável e seguro.</p>



<p>Ao longo deste artigo, vamos explorar:</p>



<ul class="wp-block-list">
<li>Como o Zephyr trata <strong>interrupções</strong> de forma portável e segura</li>



<li>Como configurar e usar <strong>ISRs (Interrupt Service Routines)</strong> corretamente</li>



<li>Como funcionam os <strong>Soft Timers (<code>k_timer</code>)</strong></li>



<li>Quando usar interrupção, timer ou thread</li>



<li>Padrões e armadilhas comuns em projetos reais</li>
</ul>



<p>Sempre com exemplos em C, comentados e aplicáveis a placas reais como STM32, nRF e RP2040.</p>



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



<h3 class="wp-block-heading"><strong>2 – Modelo de Interrupções no Zephyr: conceitos fundamentais</strong></h3>



<p>Antes de escrever qualquer ISR no Zephyr, é fundamental entender que o sistema adota um <strong>modelo de interrupções abstraído</strong>, desacoplado do hardware específico, mas ainda permitindo acesso direto quando necessário. O Zephyr se apoia em três pilares principais:</p>



<ol class="wp-block-list">
<li><strong>Árvore de dispositivos (Devicetree)</strong></li>



<li><strong>API genérica de IRQ do kernel</strong></li>



<li><strong>Separação rígida entre contexto de interrupção e contexto de thread</strong></li>
</ol>



<p>No Zephyr, interrupções <strong>não são configuradas diretamente em registradores</strong> no código da aplicação (como em bare-metal). Em vez disso, elas são declaradas e conectadas por meio do <strong>Devicetree</strong>, que descreve o hardware de forma declarativa. Isso permite que o mesmo código rode, sem modificações, em arquiteturas distintas.</p>



<h4 class="wp-block-heading"><strong>O que é uma ISR no Zephyr?</strong></h4>



<p>Uma <strong>ISR (Interrupt Service Routine)</strong> no Zephyr é uma função C comum, mas com restrições severas:</p>



<ul class="wp-block-list">
<li>Não pode bloquear</li>



<li>Não pode usar <code>k_sleep()</code></li>



<li>Não pode alocar memória dinâmica</li>



<li>Não pode chamar APIs que dependem do escalonador</li>
</ul>



<p>Ela deve apenas:</p>



<ul class="wp-block-list">
<li>Reconhecer o evento</li>



<li>Capturar dados mínimos</li>



<li>Sinalizar uma thread, timer ou workqueue</li>
</ul>



<p>Esse modelo força uma arquitetura mais limpa e previsível.</p>



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



<h3 class="wp-block-heading"><strong>3 – Conectando uma interrupção no Zephyr (exemplo com GPIO)</strong></h3>



<p>Vamos começar com um exemplo clássico: <strong>interrupção por mudança de nível em um pino GPIO</strong>, algo extremamente comum em botões, sensores e sinais externos.</p>



<h4 class="wp-block-heading"><strong>Passo 1 – Definição no Devicetree (conceito)</strong></h4>



<p>O Zephyr já fornece nós de GPIO prontos no Devicetree. Em geral, você não precisa criar nada manualmente, apenas referenciar o pino correto.</p>



<p>Exemplo conceitual (simplificado):</p>



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



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



<h4 class="wp-block-heading"><strong>Passo 2 – Estrutura de callback de GPIO</strong></h4>



<p>No Zephyr, interrupções de GPIO usam a estrutura <code>gpio_callback</code>.</p>



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

/* Callback associado à interrupção */
static struct gpio_callback button_cb_data;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#include &lt;zephyr/kernel.h&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#include &lt;zephyr/drivers/gpio.h&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">/* Callback associado à interrupção */</span></span>
<span class="line"><span style="color: #D8DEE9FF">static struct gpio_callback button_cb_data;</span></span>
<span class="line"></span></code></pre></div>



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



<h4 class="wp-block-heading"><strong>Passo 3 – Implementação da ISR</strong></h4>



<p>A função de callback será executada <strong>em contexto de interrupção</strong>:</p>



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

    /* ISR deve ser curta e não bloqueante */
    printk("Botão pressionado!\n");
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">void button_pressed_isr(const struct device *dev,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        struct gpio_callback *cb,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        uint32_t pins)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ARG_UNUSED(dev);</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ARG_UNUSED(cb);</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ARG_UNUSED(pins);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    /* ISR deve ser curta e não bloqueante */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    printk(&quot;Botão pressionado!\n&quot;);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Observação importante</strong>:<br>Mesmo o <code>printk()</code> não é ideal dentro de ISR em sistemas críticos. Ele é usado aqui apenas para fins didáticos. Em projetos reais, o correto é sinalizar uma thread.</p>



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



<h4 class="wp-block-heading"><strong>Passo 4 – Configuração do GPIO e da interrupção</strong></h4>



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

button_dev = DEVICE_DT_GET(DT_NODELABEL(gpioa));

gpio_pin_configure(button_dev, 0, GPIO_INPUT | GPIO_PULL_UP);

gpio_pin_interrupt_configure(button_dev,
                              0,
                              GPIO_INT_EDGE_FALLING);

gpio_init_callback(&amp;button_cb_data,
                   button_pressed_isr,
                   BIT(0));

gpio_add_callback(button_dev, &amp;button_cb_data);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">const struct device *button_dev;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">button_dev = DEVICE_DT_GET(DT_NODELABEL(gpioa));</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">gpio_pin_configure(button_dev, 0, GPIO_INPUT | GPIO_PULL_UP);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">gpio_pin_interrupt_configure(button_dev,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                              0,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                              GPIO_INT_EDGE_FALLING);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">gpio_init_callback(&amp;button_cb_data,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                   button_pressed_isr,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                   BIT(0));</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">gpio_add_callback(button_dev, &amp;button_cb_data);</span></span>
<span class="line"></span></code></pre></div>



<p>Neste ponto:</p>



<ul class="wp-block-list">
<li>O hardware gera a interrupção</li>



<li>O driver de GPIO chama a ISR</li>



<li>O kernel garante isolamento e segurança</li>
</ul>



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



<h3 class="wp-block-heading"><strong>4 – Arquitetura correta: ISR + sinalização de thread</strong></h3>



<p>A forma correta de usar interrupções no Zephyr é <strong>acordar ou sinalizar uma thread</strong>, e não executar lógica pesada na ISR.</p>



<p>Exemplo usando <strong>semaforos</strong>:</p>



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

void button_pressed_isr(const struct device *dev,
                        struct gpio_callback *cb,
                        uint32_t pins)
{
    k_sem_give(&amp;button_sem);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">K_SEM_DEFINE(button_sem, 0, 1);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">void button_pressed_isr(const struct device *dev,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        struct gpio_callback *cb,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        uint32_t pins)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    k_sem_give(&amp;button_sem);</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<p>Thread associada:</p>



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



<p>Essa arquitetura:</p>



<ul class="wp-block-list">
<li>Mantém ISRs determinísticas</li>



<li>Evita jitter</li>



<li>Escala melhor com múltiplos eventos</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/interrupcoes-e-soft-timers-no-zephyr-os/">Interrupções e Soft Timers no Zephyr OS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/interrupcoes-e-soft-timers-no-zephyr-os/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1244</post-id>	</item>
		<item>
		<title>Criando um Projeto Zephyr RTOS no Arduino DUE – Guia Completo e Didático</title>
		<link>https://mcu.tec.br/rtos/criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico</link>
					<comments>https://mcu.tec.br/rtos/criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 27 Mar 2026 09:01:10 +0000</pubDate>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[RTOS]]></category>
		<category><![CDATA[Arduino DUE]]></category>
		<category><![CDATA[ARM Cortex-M3]]></category>
		<category><![CDATA[firmware profissional]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[SAM3X8E]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[Zephyr Arduino]]></category>
		<category><![CDATA[Zephyr RTOS]]></category>
		<category><![CDATA[Zephyr tutorial]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1209</guid>

					<description><![CDATA[<p>Aprenda passo a passo como criar um projeto completo com Zephyr RTOS no Arduino DUE. Este tutorial detalhado e didático explica desde a estrutura do workspace, configuração do CMake e Kconfig, até a compilação, gravação e execução do firmware no microcontrolador SAM3X8E. Ideal para quem deseja sair do modelo Arduino tradicional e aprender RTOS profissional em ARM Cortex-M, com exemplos práticos, explicações profundas e foco em arquitetura de sistemas embarcados.</p>
<p>The post <a href="https://mcu.tec.br/rtos/criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico/">Criando um Projeto Zephyr RTOS no Arduino DUE – Guia Completo e Didático</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-nkf1j wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-nkf1j "><div class="eb-toc-container eb-toc-nkf1j  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;1. Introdu\u00e7\u00e3o: por que usar Zephyr no Arduino DUE&quot;,&quot;text&quot;:&quot;1. Introdu\u00e7\u00e3o: por que usar Zephyr no Arduino DUE&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;2. Vis\u00e3o geral do suporte do Zephyr ao Arduino DUE&quot;,&quot;text&quot;:&quot;2. Vis\u00e3o geral do suporte do Zephyr ao Arduino DUE&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;3. Pr\u00e9-requisitos do ambiente de desenvolvimento&quot;,&quot;text&quot;:&quot;3. Pr\u00e9-requisitos do ambiente de desenvolvimento&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;4. Estrutura recomendada de workspace&quot;,&quot;text&quot;:&quot;4. Estrutura recomendada de workspace&quot;,&quot;link&quot;:&quot;4-estrutura-recomendada-de-workspace&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5. Criando o projeto do zero para o Arduino DUE&quot;,&quot;text&quot;:&quot;5. Criando o projeto do zero para o Arduino DUE&quot;,&quot;link&quot;:&quot;5-criando-o-projeto-do-zero-para-o-arduino-due&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Criando o diret\u00f3rio da aplica\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;5.1 Criando o diret\u00f3rio da aplica\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Estrutura m\u00ednima de um projeto Zephyr&quot;,&quot;text&quot;:&quot;5.2 Estrutura m\u00ednima de um projeto Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;6. Arquivo CMakeLists.txt: integra\u00e7\u00e3o com o Zephyr&quot;,&quot;text&quot;:&quot;6. Arquivo CMakeLists.txt: integra\u00e7\u00e3o com o Zephyr&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;O que esse arquivo faz, exatamente?&quot;,&quot;text&quot;:&quot;O que esse arquivo faz, exatamente?&quot;,&quot;link&quot;:&quot;o-que-esse-arquivo-faz-exatamente&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;7. Arquivo prj.conf: configura\u00e7\u00e3o do kernel (Kconfig)&quot;,&quot;text&quot;:&quot;7. Arquivo prj.conf: configura\u00e7\u00e3o do kernel (Kconfig)&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;8. Arquivo main.c: primeira aplica\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;8. Arquivo main.c: primeira aplica\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Conceitos importantes aqui&quot;,&quot;text&quot;:&quot;Conceitos importantes aqui&quot;,&quot;link&quot;:&quot;conceitos-importantes-aqui&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;9. Compilando o projeto para o Arduino DUE&quot;,&quot;text&quot;:&quot;9. Compilando o projeto para o Arduino DUE&quot;,&quot;link&quot;:&quot;9-compilando-o-projeto-para-o-arduino-due&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;10. Gravando o firmware no Arduino DUE&quot;,&quot;text&quot;:&quot;10. Gravando o firmware no Arduino DUE&quot;,&quot;link&quot;:&quot;10-gravando-o-firmware-no-arduino-due&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;11. Pr\u00f3ximos passos&quot;,&quot;text&quot;:&quot;11. Pr\u00f3ximos passos&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;1. Introdu\u00e7\u00e3o: por que usar Zephyr no Arduino DUE&quot;,&quot;value&quot;:&quot;1-introdu\u00e7\u00e3o-por-que-usar-zephyr-no-arduino-due&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2. Vis\u00e3o geral do suporte do Zephyr ao Arduino DUE&quot;,&quot;value&quot;:&quot;2-vis\u00e3o-geral-do-suporte-do-zephyr-ao-arduino-due&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3. Pr\u00e9-requisitos do ambiente de desenvolvimento&quot;,&quot;value&quot;:&quot;3-pr\u00e9-requisitos-do-ambiente-de-desenvolvimento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4. Estrutura recomendada de workspace&quot;,&quot;value&quot;:&quot;4-estrutura-recomendada-de-workspace&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5. Criando o projeto do zero para o Arduino DUE&quot;,&quot;value&quot;:&quot;5-criando-o-projeto-do-zero-para-o-arduino-due&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Criando o diret\u00f3rio da aplica\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;51-criando-o-diret\u00f3rio-da-aplica\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Estrutura m\u00ednima de um projeto Zephyr&quot;,&quot;value&quot;:&quot;52-estrutura-m\u00ednima-de-um-projeto-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6. Arquivo CMakeLists.txt: integra\u00e7\u00e3o com o Zephyr&quot;,&quot;value&quot;:&quot;6-arquivo-cmakeliststxt-integra\u00e7\u00e3o-com-o-zephyr&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que esse arquivo faz, exatamente?&quot;,&quot;value&quot;:&quot;o-que-esse-arquivo-faz-exatamente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7. Arquivo prj.conf: configura\u00e7\u00e3o do kernel (Kconfig)&quot;,&quot;value&quot;:&quot;7-arquivo-prjconf-configura\u00e7\u00e3o-do-kernel-kconfig&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8. Arquivo main.c: primeira aplica\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;8-arquivo-mainc-primeira-aplica\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conceitos importantes aqui&quot;,&quot;value&quot;:&quot;conceitos-importantes-aqui&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;9. Compilando o projeto para o Arduino DUE&quot;,&quot;value&quot;:&quot;9-compilando-o-projeto-para-o-arduino-due&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;10. Gravando o firmware no Arduino DUE&quot;,&quot;value&quot;:&quot;10-gravando-o-firmware-no-arduino-due&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;11. Pr\u00f3ximos passos&quot;,&quot;value&quot;:&quot;11-pr\u00f3ximos-passos&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">1. Introdução: por que usar Zephyr no Arduino DUE</a><li><a href="#eb-table-content-1">2. Visão geral do suporte do Zephyr ao Arduino DUE</a><li><a href="#eb-table-content-2">3. Pré-requisitos do ambiente de desenvolvimento</a><li><a href="#4-estrutura-recomendada-de-workspace">4. Estrutura recomendada de workspace</a><li><a href="#5-criando-o-projeto-do-zero-para-o-arduino-due">5. Criando o projeto do zero para o Arduino DUE</a><ul class='eb-toc__list'><li><a href="#eb-table-content-5">5.1 Criando o diretório da aplicação</a><li><a href="#eb-table-content-6">5.2 Estrutura mínima de um projeto Zephyr</a></li></ul><li><a href="#eb-table-content-7">6. Arquivo CMakeLists.txt: integração com o Zephyr</a><ul class='eb-toc__list'><li><a href="#o-que-esse-arquivo-faz-exatamente">O que esse arquivo faz, exatamente?</a></li></ul><li><a href="#eb-table-content-9">7. Arquivo prj.conf: configuração do kernel (Kconfig)</a><li><a href="#eb-table-content-10">8. Arquivo main.c: primeira aplicação</a><ul class='eb-toc__list'><li><a href="#conceitos-importantes-aqui">Conceitos importantes aqui</a></li></ul><li><a href="#9-compilando-o-projeto-para-o-arduino-due">9. Compilando o projeto para o Arduino DUE</a><li><a href="#10-gravando-o-firmware-no-arduino-due">10. Gravando o firmware no Arduino DUE</a><li><a href="#eb-table-content-14">11. Próximos passos</a></ul></div></div></div></div></div>


<h2 class="wp-block-heading">1. Introdução: por que usar Zephyr no Arduino DUE</h2>



<p>O <strong>Zephyr Project</strong> é um sistema operacional de tempo real (RTOS – <em>Real-Time Operating System</em>) moderno, modular e altamente configurável, projetado para sistemas embarcados que exigem previsibilidade temporal, portabilidade e escalabilidade. Diferente do ecossistema Arduino tradicional — baseado em <em>superloop</em> e bibliotecas monolíticas — o Zephyr oferece um modelo arquitetural profissional, alinhado a práticas industriais, como <em>device tree</em>, <em>Kconfig</em>, <em>CMake</em> e um kernel preemptivo completo.</p>



<p>O <strong>Arduino DUE</strong> ocupa um espaço interessante nesse contexto. Baseado no microcontrolador <strong>Atmel/Microchip SAM3X8E</strong>, um ARM Cortex-M3 de 32 bits operando a 84 MHz, ele oferece recursos raros no “mundo Arduino”: barramento externo, controlador DMA (Direct Memory Access), múltiplas UARTs, SPI, TWI (I²C – <em>Inter-Integrated Circuit</em>), além de USB nativo (<em>USB OTG</em>). Esses recursos fazem do DUE uma excelente plataforma didática para aprender Zephyr em um hardware amplamente conhecido.</p>



<p>Neste artigo, você aprenderá <strong>passo a passo, de forma minuciosa</strong>, como criar um projeto Zephyr totalmente funcional para o Arduino DUE, utilizando <strong>todos os recursos documentados oficialmente</strong> pela fundação Zephyr para essa placa. O foco não será apenas “compilar e rodar”, mas <strong>entender a arquitetura do projeto</strong>, as decisões de configuração e o papel de cada arquivo envolvido.</p>



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



<h2 class="wp-block-heading">2. Visão geral do suporte do Zephyr ao Arduino DUE</h2>



<p>Antes de escrever qualquer linha de código, é fundamental entender <strong>como o Zephyr enxerga o Arduino DUE</strong>. No Zephyr, placas não são tratadas como “kits genéricos”, mas como <strong>descrições formais de hardware</strong>, compostas por:</p>



<ul class="wp-block-list">
<li><strong>Board Definition</strong>: define CPU, clock, memória e periféricos básicos</li>



<li><strong>Device Tree (DTS)</strong>: descreve os dispositivos de hardware de forma declarativa</li>



<li><strong>Kconfig da placa</strong>: habilita ou restringe funcionalidades do kernel</li>



<li><strong>Arquivos de build</strong>: integram a placa ao sistema CMake do Zephyr</li>
</ul>



<p>No caso do Arduino DUE, o Zephyr fornece oficialmente:</p>



<ul class="wp-block-list">
<li>Arquivo de <em>board</em> baseado no <strong>SAM3X8E</strong></li>



<li>Mapeamento correto de pinos compatível com o layout do DUE</li>



<li>Suporte a:
<ul class="wp-block-list">
<li>GPIO (General Purpose Input/Output)</li>



<li>UART (console serial)</li>



<li>SPI</li>



<li>I²C (TWI no SAM)</li>



<li>Temporizadores e <em>SysTick</em></li>
</ul>
</li>



<li>Programação via <strong>porta USB de programação</strong> (a mesma usada com o bossac)</li>
</ul>



<p>Isso significa que <strong>não é necessário criar uma placa customizada</strong> para começar: o Arduino DUE já está plenamente integrado ao ecossistema Zephyr.</p>



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



<h2 class="wp-block-heading">3. Pré-requisitos do ambiente de desenvolvimento</h2>



<p>Antes de criar o projeto, o ambiente Zephyr <strong>precisa estar corretamente instalado</strong>. Assumiremos aqui que você já leu os artigos anteriores da série e possui:</p>



<ul class="wp-block-list">
<li>Linux (Ubuntu 22.04 ou superior recomendado)</li>



<li>Python 3.10+</li>



<li><code>west</code> (ferramenta de meta-build do Zephyr)</li>



<li>Zephyr SDK instalada</li>



<li>Toolchain ARM embarcada funcional</li>
</ul>



<p>Para validar rapidamente se o ambiente está correto, execute:</p>



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



<p>E depois:</p>



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



<p>Se o ambiente estiver correto, você verá a placa <strong>arduino_due</strong> listada entre as placas suportadas. Esse comando é extremamente importante: ele confirma que o Zephyr <strong>reconhece oficialmente</strong> o Arduino DUE no seu workspace.</p>



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



<h2 class="wp-block-heading">4. Estrutura recomendada de workspace</h2>



<p>Um erro comum entre iniciantes é misturar código de aplicação com o repositório do Zephyr. A abordagem correta é usar um <strong>workspace limpo</strong>, com a seguinte estrutura conceitual:</p>



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



<p>Dentro da pasta <code>arduino_due_app</code>, ficará <strong>apenas o código da aplicação</strong>, sem dependências diretas do kernel. Essa separação é crucial para manter o projeto sustentável e escalável.</p>



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



<h2 class="wp-block-heading">5. Criando o projeto do zero para o Arduino DUE</h2>



<p>Agora vamos criar efetivamente o projeto.</p>



<h3 class="wp-block-heading">5.1 Criando o diretório da aplicação</h3>



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



<h3 class="wp-block-heading">5.2 Estrutura mínima de um projeto Zephyr</h3>



<p>Crie a seguinte estrutura inicial:</p>



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



<p>Essa é a <strong>estrutura mínima obrigatória</strong> para qualquer aplicação Zephyr.</p>



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



<h2 class="wp-block-heading">6. Arquivo <code>CMakeLists.txt</code>: integração com o Zephyr</h2>



<p>Crie o arquivo <code>CMakeLists.txt</code> com o conteúdo:</p>



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

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(arduino_due_app)

target_sources(app PRIVATE src/main.c)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">cmake_minimum_required(VERSION 3.20.0)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})</span></span>
<span class="line"><span style="color: #D8DEE9FF">project(arduino_due_app)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">target_sources(app PRIVATE src/main.c)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">O que esse arquivo faz, exatamente?</h3>



<ul class="wp-block-list">
<li><code>cmake_minimum_required</code>: garante compatibilidade mínima do CMake</li>



<li><code>find_package(Zephyr ...)</code>: importa todo o sistema de build do Zephyr</li>



<li><code>project(...)</code>: define o nome lógico do projeto</li>



<li><code>target_sources(...)</code>: registra os arquivos C da aplicação</li>
</ul>



<p>Aqui ocorre algo importante: <strong>você não define compilador, flags ou linker script</strong>. Tudo isso é herdado automaticamente da definição da placa (<code>arduino_due</code>) e do kernel.</p>



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



<h2 class="wp-block-heading">7. Arquivo <code>prj.conf</code>: configuração do kernel (Kconfig)</h2>



<p>O <code>prj.conf</code> controla <strong>quais partes do kernel Zephyr serão compiladas</strong>.</p>



<p>Comece com o mínimo funcional:</p>



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



<p>Essas opções habilitam:</p>



<ul class="wp-block-list">
<li><code>printk()</code> – saída básica de debug</li>



<li>Driver de porta serial</li>



<li>Console padrão via UART</li>
</ul>



<p>No Arduino DUE, isso será mapeado automaticamente para a UART correta definida no <em>device tree</em> da placa.</p>



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



<h2 class="wp-block-heading">8. Arquivo <code>main.c</code>: primeira aplicação</h2>



<p>Crie <code>src/main.c</code>:</p>



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

int main(void)
{
    printk("Zephyr rodando no Arduino DUE!\n");

    while (1) {
        printk("Tick\n");
        k_sleep(K_SECONDS(1));
    }

    return 0;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#include &lt;zephyr/kernel.h&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#include &lt;zephyr/sys/printk.h&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">int main(void)</span></span>
<span class="line"><span style="color: #D8DEE9FF">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    printk(&quot;Zephyr rodando no Arduino DUE!\n&quot;);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    while (1) {</span></span>
<span class="line"><span style="color: #D8DEE9FF">        printk(&quot;Tick\n&quot;);</span></span>
<span class="line"><span style="color: #D8DEE9FF">        k_sleep(K_SECONDS(1));</span></span>
<span class="line"><span style="color: #D8DEE9FF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    return 0;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Conceitos importantes aqui</h3>



<ul class="wp-block-list">
<li><code>#include &lt;zephyr/kernel.h&gt;</code>: acesso ao kernel, threads e temporização</li>



<li><code>printk()</code>: saída síncrona simples (não é <code>printf</code>)</li>



<li><code>k_sleep()</code>: API de temporização do kernel</li>



<li><code>main()</code> <strong>existe</strong>, mas não é o ponto de entrada real — o kernel já está inicializado antes dela ser chamada</li>
</ul>



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



<h2 class="wp-block-heading">9. Compilando o projeto para o Arduino DUE</h2>



<p>Agora vem a parte crítica: <strong>build correto para a placa certa</strong>.</p>



<p>Dentro da pasta <code>arduino_due_app</code>:</p>



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



<p>O Zephyr irá:</p>



<ol class="wp-block-list">
<li>Ler a definição da placa Arduino DUE</li>



<li>Selecionar o SoC SAM3X8E</li>



<li>Configurar clocks, memória e periféricos</li>



<li>Gerar o firmware final</li>
</ol>



<p>Se tudo estiver correto, o build terminará sem erros.</p>



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



<h2 class="wp-block-heading">10. Gravando o firmware no Arduino DUE</h2>



<p>O Arduino DUE utiliza o <strong>bootloader SAM-BA</strong>, compatível com a ferramenta <code>bossac</code>.</p>



<p>Com a placa conectada via <strong>porta USB de programação</strong>, execute:</p>



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



<p>O Zephyr cuidará automaticamente do processo de gravação usando o método correto definido para a placa.</p>



<p>Após o reset, abra um terminal serial:</p>



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



<p>Você deverá ver:</p>



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



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



<h2 class="wp-block-heading">11. Próximos passos</h2>



<p>A partir daqui, você já tem:</p>



<ul class="wp-block-list">
<li>Um projeto Zephyr funcional</li>



<li>Build e flash corretamente configurados</li>



<li>Console serial ativo</li>



<li>Base sólida para evoluir</li>
</ul>



<p>Nos próximos artigos, podemos avançar para:</p>



<ul class="wp-block-list">
<li>Device Tree do Arduino DUE em detalhes</li>



<li>GPIO e LEDs</li>



<li>UARTs adicionais</li>



<li>SPI e I²C</li>



<li>Timers e interrupções</li>



<li>Multithreading real no Cortex-M3</li>
</ul>



<p></p><p>The post <a href="https://mcu.tec.br/rtos/criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico/">Criando um Projeto Zephyr RTOS no Arduino DUE – Guia Completo e Didático</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/criando-um-projeto-zephyr-rtos-no-arduino-due-guia-completo-e-didatico/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1209</post-id>	</item>
		<item>
		<title>Padrões de Projeto Aplicados a RTOS (FreeRTOS)</title>
		<link>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=padroes-de-projeto-aplicados-a-rtos-freertos-2</link>
					<comments>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 20 Mar 2026 08:29:27 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura de firmware]]></category>
		<category><![CDATA[comunicação entre tarefas FreeRTOS]]></category>
		<category><![CDATA[firmware robusto]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[inicialização em RTOS]]></category>
		<category><![CDATA[máquinas de estado em FreeRTOS]]></category>
		<category><![CDATA[mutex e gatekeeper FreeRTOS]]></category>
		<category><![CDATA[padrões de projeto embarcados]]></category>
		<category><![CDATA[RTOS em sistemas embarcados]]></category>
		<category><![CDATA[sistemas de tempo real]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1206</guid>

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



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



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



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



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



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



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



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



<p><strong>Ideia do padrão:</strong><br>Manter o superloop como uma <strong>tarefa principal</strong>, introduzindo gradualmente novas tarefas RTOS.</p>



<p><strong>Quando usar:</strong></p>



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



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



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



<p><strong>Estrutura típica:</strong></p>



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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Tarefas que fazem “de tudo” dificultam análise temporal, debugging e escalonamento.</p>



<p><strong>Ideia do padrão:</strong><br>Cada tarefa possui <strong>uma única responsabilidade funcional bem definida</strong>.</p>



<p><strong>Exemplo típico em FreeRTOS:</strong></p>



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



<li>Task de processamento</li>



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



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



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



<p><strong>Vantagens:</strong></p>



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



<li>Reduz acoplamento</li>



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



<p><strong>Boas práticas:</strong></p>



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Algumas aplicações precisam de <strong>periodicidade rígida</strong>, mesmo usando RTOS.</p>



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



<p><strong>Estrutura conceitual:</strong></p>



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



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



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

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

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



<p><strong>Vantagens:</strong></p>



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



<li>Previsibilidade elevada</li>



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



<p><strong>Limitação:</strong><br>Menos flexível que arquiteturas puramente orientadas a eventos.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Desperdício de CPU e energia quando o sistema está ocioso.</p>



<p><strong>Ideia do padrão:</strong><br>Usar a <strong>Idle Task</strong> como ponto central para:</p>



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



<li>Limpeza de recursos</li>



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



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



<p><strong>Uso típico:</strong></p>



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



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



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



<p><strong>Importante:</strong><br>Nunca bloquear, nunca usar delays e nunca acessar recursos não protegidos.</p>



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



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



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



<p>Aqui falamos de <strong>comunicação</strong>, não apenas de sincronização.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Múltiplos produtores gerando eventos assíncronos para um único consumidor.</p>



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



<p><strong>Quando usar:</strong></p>



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



<li>Eventos de sensores</li>



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



<p><strong>Estrutura típica do evento:</strong></p>



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

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



<p><strong>Fila global (criada na inicialização):</strong></p>



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

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



<p><strong>Produtor:</strong></p>



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

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

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



<p><strong>Consumidor:</strong></p>



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

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

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

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



<p><strong>Vantagens:</strong></p>



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



<li>Ordem garantida</li>



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



<p><strong>Erro comum:</strong><br>Usar fila para <strong>stream contínuo de dados</strong> (para isso existem buffers).</p>



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



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



<p><strong>Problema resolvido:</strong><br>Apenas <strong>o último valor importa</strong>, não o histórico.</p>



<p><strong>Ideia do padrão:</strong><br>Uma fila de tamanho 1 funciona como <strong>mailbox sobrescrevível</strong>.</p>



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

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



<p><strong>Produtor:</strong></p>



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



<p><strong>Consumidor:</strong></p>



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

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



<p><strong>Quando usar:</strong></p>



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



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



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



<p><strong>Vantagem-chave:</strong><br>Evita backlog artificial.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Múltiplos consumidores interessados no mesmo evento.</p>



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



<p><strong>Arquitetura:</strong></p>



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



<p><strong>Dispatcher:</strong></p>



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

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



<p><strong>Vantagens:</strong></p>



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



<li>Isola produtores de consumidores</li>



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



<p><strong>Custo:</strong><br>Mais RAM e latência — aceitável em troca de clareza.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Overhead de filas quando apenas <strong>sinalização simples</strong> é necessária.</p>



<p><strong>Ideia do padrão:</strong><br>Usar <strong>Task Notifications</strong> como semáforos ultraleves.</p>



<p><strong>Produtor:</strong></p>



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



<p><strong>Consumidor:</strong></p>



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

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

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



<p><strong>Vantagens:</strong></p>



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



<li>Extremamente rápido</li>



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



<p><strong>Limitação:</strong><br>Apenas 32 bits por tarefa → não serve para dados complexos.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Troca eficiente de <strong>fluxos contínuos</strong> de dados.</p>



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



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



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



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



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



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



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



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



<p><strong>Uso típico:</strong></p>



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



<li>SPI</li>



<li>Áudio</li>



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



<p><strong>Boa prática:</strong><br>Preferir buffers a filas para dados “em volume”.</p>



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



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



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



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



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



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



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



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



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

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



<p><strong>Uso correto:</strong></p>



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



<p><strong>Por que não semáforo binário?</strong></p>



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Múltiplas tarefas acessando um <strong>único periférico</strong> (UART, Flash, Display).</p>



<p><strong>Ideia do padrão:</strong><br>Apenas <strong>uma tarefa é dona do recurso</strong>. As demais <strong>pedem serviço</strong> via fila.</p>



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



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



<p><strong>Estrutura:</strong></p>



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



<p><strong>Mensagem de requisição:</strong></p>



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



<p><strong>Gatekeeper:</strong></p>



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

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



<p><strong>Cliente:</strong></p>



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



<p><strong>Vantagens:</strong></p>



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



<li>Elimina deadlocks</li>



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



<p><strong>Trade-off:</strong><br>Leve aumento de latência → ganho enorme em robustez.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Trechos <strong>extremamente curtos</strong> que não podem ser interrompidos.</p>



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



<p><strong>O que acontece:</strong></p>



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



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



<p><strong>Quando usar:</strong></p>



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



<li>Flags simples</li>



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



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



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



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



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



<p><strong>Problema comum (ERRADO):</strong></p>



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



<p><strong>Correção com mutex:</strong></p>



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



<p><strong>Ou melhor ainda:</strong><br>Substituir <code>flag</code> por <strong>task notification</strong> ou <strong>event group</strong>.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Sincronizar múltiplas tarefas com <strong>condições compostas</strong>.</p>



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

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



<p><strong>Sinalização:</strong></p>



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



<p><strong>Aguardar múltiplas condições:</strong></p>



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



<p><strong>Uso típico:</strong></p>



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



<li>Estados globais do sistema</li>



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



<p><strong>Vantagem:</strong><br>Muito mais expressivo que flags globais.</p>



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



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



<p><strong>Causa clássica de deadlock:</strong></p>



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



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



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

/* uso */

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



<p><strong>Alternativa mais segura:</strong><br>Eliminar múltiplos mutexes → usar <strong>Gatekeeper</strong>.</p>



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



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Fluxo de controle espalhado por múltiplas tarefas e condicionais.</p>



<p><strong>Ideia do padrão:</strong><br>Representar o comportamento como <strong>estados explícitos</strong> e <strong>transições bem definidas</strong>.</p>



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



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



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



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



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



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



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

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

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

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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



<p><strong>Limitação:</strong><br>Cresce mal quando há muitos estados e eventos → entra a HSM.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Explosão combinatória de estados.</p>



<p><strong>Ideia do padrão:</strong><br>Estados possuem <strong>comportamento comum herdado</strong> de estados “pais”.</p>



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



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



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



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



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



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

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

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



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

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

            break;

        case SUPER_FAULT:
            HandleFaultCommon();

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

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



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



<p><strong>Vantagens:</strong></p>



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



<li>Escala bem</li>



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



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



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



<p><strong>Problema resolvido:</strong><br>Múltiplas tarefas precisam reagir a <strong>mudanças globais de modo</strong>.</p>



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



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



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



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



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



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



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

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

        if (MaintenanceRequested())
            currentMode = MODE_MAINTENANCE;

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



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



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



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

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



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



<p><strong>Boa prática:</strong><br>Substituir variável global por:</p>



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



<li>Message Queue</li>



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



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



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



<p><strong>Problema resolvido:</strong><br>Falhas transitórias travam o sistema.</p>



<p><strong>Ideia do padrão:</strong><br>Falhas são tratadas como <strong>estados</strong>, não exceções implícitas.</p>



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



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



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



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



<p><strong>Vantagens:</strong></p>



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



<li>Permite retry controlado</li>



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



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



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



<p><strong>Problema resolvido:</strong><br>Deadlocks silenciosos e travamentos não detectados.</p>



<p><strong>Ideia do padrão:</strong><br>Cada tarefa <strong>sinaliza vida</strong> periodicamente para um supervisor.</p>



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



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

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



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



<p><strong>Importante:</strong><br>O watchdog <strong>não substitui</strong> arquitetura correta — ele a complementa.</p>



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



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



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



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



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



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



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



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



<p><strong>Ideia do padrão:</strong><br>Organizar o sistema em <strong>camadas bem definidas</strong>, com dependências unidirecionais.</p>



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



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



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



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



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



<p><strong>Driver (HAL):</strong></p>



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



<p><strong>Serviço:</strong></p>



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



<p><strong>Aplicação:</strong></p>



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



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



<p><strong>Vantagens:</strong></p>



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



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Dependência direta de registradores ou SDK do fabricante.</p>



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



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



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



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



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



<p><strong>Benefício crítico:</strong><br>Permite trocar STM32 → NXP → RP2040 <strong>sem reescrever aplicação</strong>.</p>



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



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



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



<p><strong>Ideia do padrão:</strong><br>Serviços encapsulam:</p>



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



<li>Filas</li>



<li>Retries</li>



<li>Timeout</li>



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



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



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



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

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



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



<p><strong>Vantagens:</strong></p>



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



<li>Política centralizada</li>



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



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



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



<p><strong>Problema resolvido:</strong><br>Misturar lógica de controle com concorrência explícita.</p>



<p><strong>Ideia do padrão:</strong><br>Cada objeto ativo possui:</p>



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



<li>Fila própria</li>



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



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



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



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



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



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



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



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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



<p><strong>Custo:</strong><br>Uso maior de RAM (1 task + 1 fila por objeto)</p>



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



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



<p><strong>Problema resolvido:</strong><br>ISR longa causa jitter e perda de deadlines.</p>



<p><strong>Ideia do padrão:</strong><br>ISR apenas <strong>sinaliza</strong> → processamento pesado ocorre em task.</p>



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



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



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



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



<p><strong>Vantagens:</strong></p>



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



<li>Melhor escalonamento</li>



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



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



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



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



<p>Os padrões desta seção tornam o startup <strong>determinístico, auditável e recuperável</strong>.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Inicialização espalhada entre <code>main()</code>, ISRs e tarefas diversas.</p>



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



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



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



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

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

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



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

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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



<p><strong>Boa prática:</strong><br>Startup task deve <strong>se autodestruir</strong> após cumprir sua função.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Tarefas começam a rodar antes de suas dependências estarem prontas.</p>



<p><strong>Ideia do padrão:</strong><br>Inicialização ocorre em <strong>fases bem definidas</strong>, com sincronização explícita.</p>



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



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



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



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

    InitServices();
    xEventGroupSetBits(systemEvents, EVT_SERVICES_READY);

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



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

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



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



<p><strong>Vantagem:</strong><br>Dependências explícitas → menos bugs “fantasma”.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Serviços que dependem implicitamente uns dos outros.</p>



<p><strong>Ideia do padrão:</strong><br>Cada serviço <strong>declara o que precisa</strong> antes de operar.</p>



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



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



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



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

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



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



<p><strong>Melhoria recomendada:</strong><br>Substituir polling por <strong>eventos ou notificações</strong>.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Tarefas travam silenciosamente.</p>



<p><strong>Ideia do padrão:</strong><br>Cada tarefa reporta periodicamente seu estado para um <strong>supervisor central</strong>.</p>



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



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



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



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



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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Sistema entra em estado indefinido após falha grave.</p>



<p><strong>Ideia do padrão:</strong><br>Definir explicitamente um <strong>estado seguro</strong>, conhecido e controlado.</p>



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



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



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



<p><strong>Importante:</strong><br>Fail-safe <strong>não é reset</strong>. É sobrevivência controlada.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Reset total desnecessário causa perda de estado e latência.</p>



<p><strong>Ideia do padrão:</strong><br>Diferenciar:</p>



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



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



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



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



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



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



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



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



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



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



<p>Podemos organizar os padrões apresentados em <strong>camadas de decisão</strong>, do mais fundamental ao mais sistêmico:</p>



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



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



<li>One Task per Responsibility</li>



<li>Cyclic Executive</li>



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



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



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



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



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



<li>Mailbox</li>



<li>Publish–Subscribe</li>



<li>Task Notifications</li>



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



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



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



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



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



<li>Gatekeeper Task</li>



<li>Critical Sections</li>



<li>Event Groups</li>



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



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



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



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



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



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



<li>Mode Manager</li>



<li>Recovery Pattern</li>



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



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



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



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



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



<li>HAL</li>



<li>Service Layer</li>



<li>Active Object</li>



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



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



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



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



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



<li>Init Sequencing</li>



<li>Dependency Ordering</li>



<li>Health Monitoring</li>



<li>Fail-Safe State</li>



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



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



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



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



<p>Use este checklist como <strong>ferramenta de revisão técnica</strong>:</p>



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



<p>Todos esses erros são <strong>sintomas da ausência de padrões</strong>, não de falta de RTOS.</p>



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



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



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



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



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



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



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



<li>Retrabalho arquitetural</li>



<li>Risco em produção</li>
</ul><p>The post <a href="https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/">Padrões de Projeto Aplicados a RTOS (FreeRTOS)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1206</post-id>	</item>
		<item>
		<title>Padrões de Projeto Aplicados a RTOS (FreeRTOS)</title>
		<link>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=padroes-de-projeto-aplicados-a-rtos-freertos</link>
					<comments>https://mcu.tec.br/rtos/padroes-de-projeto-aplicados-a-rtos-freertos/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 13 Mar 2026 15:48:51 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura de firmware]]></category>
		<category><![CDATA[comunicação entre tarefas FreeRTOS]]></category>
		<category><![CDATA[firmware robusto]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[inicialização em RTOS]]></category>
		<category><![CDATA[máquinas de estado em FreeRTOS]]></category>
		<category><![CDATA[mutex e gatekeeper FreeRTOS]]></category>
		<category><![CDATA[padrões de projeto embarcados]]></category>
		<category><![CDATA[RTOS em sistemas embarcados]]></category>
		<category><![CDATA[sistemas de tempo real]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1198</guid>

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


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



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



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



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



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



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



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



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



<p><strong>Ideia do padrão:</strong><br>Manter o superloop como uma <strong>tarefa principal</strong>, introduzindo gradualmente novas tarefas RTOS.</p>



<p><strong>Quando usar:</strong></p>



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



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



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



<p><strong>Estrutura típica:</strong></p>



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

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



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



<p><strong>Vantagens:</strong></p>



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



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Tarefas que fazem “de tudo” dificultam análise temporal, debugging e escalonamento.</p>



<p><strong>Ideia do padrão:</strong><br>Cada tarefa possui <strong>uma única responsabilidade funcional bem definida</strong>.</p>



<p><strong>Exemplo típico em FreeRTOS:</strong></p>



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



<li>Task de processamento</li>



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



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



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



<p><strong>Vantagens:</strong></p>



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



<li>Reduz acoplamento</li>



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



<p><strong>Boas práticas:</strong></p>



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



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



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



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



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



<p><strong>Problema resolvido:</strong><br>Algumas aplicações precisam de <strong>periodicidade rígida</strong>, mesmo usando RTOS.</p>



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



<p><strong>Estrutura conceitual:</strong></p>



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



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



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

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

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



<p><strong>Vantagens:</strong></p>



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



<li>Previsibilidade elevada</li>



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



<p><strong>Limitação:</strong><br>Menos flexível que arquiteturas puramente orientadas a eventos.</p>



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



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



<p><strong>Problema resolvido:</strong><br>Desperdício de CPU e energia quando o sistema está ocioso.</p>



<p><strong>Ideia do padrão:</strong><br>Usar a <strong>Idle Task</strong> como ponto central para:</p>



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



<li>Limpeza de recursos</li>



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



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



<p><strong>Uso típico:</strong></p>



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



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



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



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

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



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



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



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



<p>Nesta série de artigos, este material assume um <strong>cenário típico e realista</strong>:</p>



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



<p>Assumiremos um cenário bastante comum em projetos industriais:</p>



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



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



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



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



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



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



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



<p>A sequência correta, em alto nível, é:</p>



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



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



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



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



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



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



<p>Essa ordem garante que nenhuma task tente acessar a pilha TCP/IP fora do contexto correto.</p>



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



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



<p>O primeiro ponto de integração direta entre FreeRTOS e lwIP é a chamada a <code>tcpip_init()</code>:</p>



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

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

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



<p>O que acontece aqui, de fato:</p>



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



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



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



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



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



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



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



<p>Após a inicialização do lwIP, precisamos registrar a interface de rede:</p>



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

static struct netif netif_eth;

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

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

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

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

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



<p>Aqui aparecem alguns pontos arquiteturais importantes:</p>



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



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



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



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



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



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



<p>Somente depois que a pilha está pronta é que criamos tasks que usam rede:</p>



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

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



<p>Note que:</p>



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



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



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



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



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



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



<p>Alguns problemas recorrentes que surgem exatamente nesse ponto:</p>



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



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



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



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



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



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



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



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



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



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



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



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



<p>Para usar Sockets no lwIP você normalmente precisa ter (no <code>lwipopts.h</code>):</p>



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



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



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



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



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



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



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



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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



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



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



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



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



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



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



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



<p>Um exemplo direto para evitar travar em <code>recv()</code>:</p>



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



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



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



<p>Na próxima seção, vamos fazer exatamente o que transforma esse exemplo em arquitetura “de produção”:</p>



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



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



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



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



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



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



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



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



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



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



<p>Vamos definir duas filas:</p>



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



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



<p>Cada mensagem precisa carregar, no mínimo:</p>



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



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



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



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



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

#define MAX_PAYLOAD 512

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

static QueueHandle_t rxQueue;
static QueueHandle_t txQueue;

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



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



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



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



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



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

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

#define SERVER_PORT 5000

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

    int listen_fd;
    struct sockaddr_in addr;

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

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

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

    if (listen(listen_fd, 4) &lt; 0) {
        closesocket(listen_fd);
        vTaskDelete(NULL);
    }

    for (;;)
    {
        int client_fd = accept(listen_fd, NULL, NULL);
        if (client_fd &lt; 0) {
            vTaskDelay(pdMS_TO_TICKS(50));
            continue;
        }

        /* Exemplo simples: atende 1 cliente por vez.
           Em produção você pode criar uma task por cliente OU usar select(). */
        for (;;)
        {
            NetMessage_t msg;
            int n = recv(client_fd, msg.payload, MAX_PAYLOAD, 0);
            if (n &lt;= 0) break;

            msg.client_fd = client_fd;
            msg.len = (uint16_t)n;

            /* Entrega para aplicação: se a fila estiver cheia, você precisa decidir política:
               - descartar
               - bloquear por tempo limitado
               - desconectar cliente
            */
            if (xQueueSend(rxQueue, &amp;msg, pdMS_TO_TICKS(20)) != pdPASS) {
                /* Política simples: descarta e segue */
            }

            /* Antes de receber mais, veja se há resposta pronta para este cliente */
            NetMessage_t out;
            if (xQueueReceive(txQueue, &amp;out, 0) == pdPASS) {
                if (out.client_fd == client_fd &amp;&amp; out.len > 0) {
                    send(client_fd, out.payload, out.len, 0);
                } else {
                    /* Se veio resposta de outro cliente, em produção você
                       rotearia corretamente (mapa de conexões, etc.) */
                }
            }
        }

        closesocket(client_fd);
    }
}

void start_socket_gatekeeper(void)
{
    xTaskCreate(socket_gatekeeper_task,
                "NetGate",
                2048,
                NULL,
                tskIDLE_PRIORITY + 3, /* Um pouco acima da aplicação */
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">queue.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/sockets.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">lwip/inet.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5000</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket_gatekeeper_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr_in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">addr</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AF_INET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOCK_STREAM</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_family</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AF_INET</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_port</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htons</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SERVER_PORT</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sin_addr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">s_addr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">htonl</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">INADDR_ANY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">bind</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sockaddr</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">addr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">addr</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">listen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">accept</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">listen_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">50</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Exemplo simples: atende 1 cliente por vez.</span></span>
<span class="line"><span style="color: #616E88">           Em produção você pode criar uma task por cliente OU usar select(). */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">recv</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_PAYLOAD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">n</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Entrega para aplicação: se a fila estiver cheia, você precisa decidir política:</span></span>
<span class="line"><span style="color: #616E88">               - descartar</span></span>
<span class="line"><span style="color: #616E88">               - bloquear por tempo limitado</span></span>
<span class="line"><span style="color: #616E88">               - desconectar cliente</span></span>
<span class="line"><span style="color: #616E88">            */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rxQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">20</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #616E88">/* Política simples: descarta e segue */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Antes de receber mais, veja se há resposta pronta para este cliente */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">send</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #616E88">/* Se veio resposta de outro cliente, em produção você</span></span>
<span class="line"><span style="color: #616E88">                       rotearia corretamente (mapa de conexões, etc.) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">start_socket_gatekeeper</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">socket_gatekeeper_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">NetGate</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* Um pouco acima da aplicação */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p><strong>Por que esse desenho é bom?</strong> Porque o Gatekeeper mantém I/O simples e previsível: ele não interpreta protocolo nem acessa hardware. Ele apenas “empurra bytes”.</p>



<p><strong>Crítica (importante):</strong> este exemplo atende um cliente por vez. Para múltiplos clientes, as duas opções típicas são:</p>



<ol class="wp-block-list">
<li><strong>uma task por conexão</strong> (mais simples, mas consome RAM/stack)</li>



<li><strong><code>select()</code></strong> com um loop único multiplexando sockets (mais eficiente, mais complexo)</li>
</ol>



<p>Na próxima seção eu te mostro os dois modelos, mas antes precisamos fechar o ciclo com o consumidor.</p>



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



<h4 class="wp-block-heading"><strong>7.3 Task consumidora: processa mensagem e devolve resposta</strong></h4>



<p>Agora a lógica de aplicação recebe mensagens da <code>rxQueue</code>, interpreta e devolve uma resposta pela <code>txQueue</code>.</p>



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

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

    for (;;)
    {
        NetMessage_t in;
        if (xQueueReceive(rxQueue, &amp;in, portMAX_DELAY) == pdPASS)
        {
            NetMessage_t out;
            memset(&amp;out, 0, sizeof(out));

            out.client_fd = in.client_fd;

            /* Exemplo de "protocolo": comandos ASCII */
            if (in.len >= 4 &amp;&amp; memcmp(in.payload, "ping", 4) == 0) {
                const char *resp = "pong\n";
                out.len = (uint16_t)strlen(resp);
                memcpy(out.payload, resp, out.len);
            } else {
                const char *resp = "unknown\n";
                out.len = (uint16_t)strlen(resp);
                memcpy(out.payload, resp, out.len);
            }

            /* Envia resposta para o Gatekeeper transmitir */
            (void)xQueueSend(txQueue, &amp;out, pdMS_TO_TICKS(50));
        }
    }
}

void start_app_worker(void)
{
    xTaskCreate(app_worker_task,
                "AppWorker",
                2048,
                NULL,
                tskIDLE_PRIORITY + 2,
                NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">FreeRTOS.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">task.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">queue.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">app_worker_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">rxQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;in</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">NetMessage_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">client_fd</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Exemplo de &quot;protocolo&quot;: comandos ASCII */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">memcmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">in</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ping</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">pong</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">resp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">unknown</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">resp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">resp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Envia resposta para o Gatekeeper transmitir */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">out</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">50</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">start_app_worker</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xTaskCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">app_worker_task</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">AppWorker</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">tskIDLE_PRIORITY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Aqui você ganhou algo decisivo: se o parsing for pesado, você pode criar <strong>vários workers consumidores</strong> (ou uma pool) sem mexer na task de rede. E se um worker travar, você pode reiniciá-lo sem derrubar a rede (principalmente se tiver Task Monitor/Watchdog como você já vem tratando na série).</p>



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



<h4 class="wp-block-heading"><strong>7.4 Ajustes essenciais para “produção”</strong></h4>



<p>O exemplo acima é a forma didática mais direta, mas em firmware real você geralmente aplica melhorias:</p>



<ul class="wp-block-list">
<li><strong>Roteamento de respostas por conexão:</strong> em vez de uma <code>txQueue</code> única, você cria uma fila por cliente (ou um mapa de conexões).</li>



<li><strong>Política de backpressure:</strong> se <code>rxQueue</code> enche, você reduz leitura do socket, aplica <code>recv</code> com timeout, ou desconecta cliente.</li>



<li><strong>Framing:</strong> TCP é stream, não pacote. Seu “comando” pode vir partido em múltiplos <code>recv()</code>. Então você implementa <em>framing</em> (por delimitador <code>\n</code>, por tamanho fixo, ou por header com length).</li>



<li><strong>Stack e heap:</strong> payload copiado custa RAM; quando necessário, migra para pool de buffers.</li>
</ul>



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



<p>Na próxima seção, vamos atacar exatamente o que separa “demo” de “produto”:<br><strong>TCP é stream — então precisamos de framing e parser robusto</strong>, além de <strong>timeouts</strong> e <strong>manuseio de múltiplos clientes</strong>.</p>



<h3 class="wp-block-heading"><strong> TCP é stream: framing robusto + múltiplos clientes (task por conexão vs <code>select()</code>)</strong></h3>



<p>Se tem um erro conceitual que derruba sistemas FreeRTOS + lwIP “do nada”, é tratar <code>recv()</code> como se cada chamada retornasse uma mensagem completa. <strong>TCP não entrega mensagens — entrega um fluxo (stream)</strong>. Isso significa que um comando <code>ping\n</code> pode chegar como <code>p</code>, depois <code>ing\n</code>, ou pode chegar junto com outro comando colado, ou pode vir com bytes extras. Se você não implementar <strong>framing</strong>, sua aplicação vai funcionar em bancada e falhar sob carga, ruído de rede, latência variável ou retransmissões.</p>



<p>A solução arquitetural é definir um protocolo com framing claro. Os dois modelos mais comuns em firmware são: (1) <strong>delimitador</strong> (por exemplo <code>\n</code>) e (2) <strong>length-prefix</strong> (header com tamanho). Vou te mostrar os dois, e em seguida mostro como isso muda quando você tem múltiplos clientes: ou você cria <strong>uma task por conexão</strong> (simples, mais RAM) ou usa <strong><code>select()</code></strong> (eficiente, mais complexo).</p>



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



<h4 class="wp-block-heading"><strong>8.1 Framing por delimitador (<code>\n</code>)</strong></h4>



<p>Esse é o mais simples: você acumula bytes num buffer até achar <code>\n</code>. Cada linha vira um comando. É ótimo para console TCP, debug remoto, protocolos ASCII e comandos humanos. O cuidado é evitar overflow: se o cliente mandar uma linha enorme sem <code>\n</code>, você precisa cortar, descartar ou desconectar.</p>



<p>Exemplo de acumulador por conexão:</p>



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

#define LINE_BUF_SZ 256

typedef struct
{
    uint8_t buf&#91;LINE_BUF_SZ&#93;;
    uint16_t used;
} LineFramer_t;

/**
 * @brief Alimenta o framer com bytes recebidos e extrai 0..N linhas completas.
 *        Retorna 1 quando extraiu uma linha, 0 quando ainda não tem linha.
 */
static int framer_try_get_line(LineFramer_t *f, const uint8_t *data, uint16_t len,
                               uint8_t *out_line, uint16_t *out_len)
{
    /* Copia com proteção */
    uint16_t space = (LINE_BUF_SZ - 1) - f->used;
    if (len > space) {
        /* Política simples: reset (em produção: desconectar cliente) */
        f->used = 0;
        return 0;
    }

    memcpy(&amp;f->buf&#91;f->used&#93;, data, len);
    f->used += len;
    f->buf&#91;f->used&#93; = 0;

    /* Procura delimitador */
    uint8_t *nl = (uint8_t*)memchr(f->buf, '\n', f->used);
    if (!nl) return 0;

    uint16_t line_len = (uint16_t)(nl - f->buf) + 1; /* inclui '\n' */
    memcpy(out_line, f->buf, line_len);
    *out_len = line_len;

    /* Remove a linha do buffer (shift) */
    uint16_t remaining = f->used - line_len;
    memmove(f->buf, &amp;f->buf&#91;line_len&#93;, remaining);
    f->used = remaining;

    return 1;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">256</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">used</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Alimenta o framer com bytes recebidos e extrai 0..N linhas completas.</span></span>
<span class="line"><span style="color: #616E88"> *        Retorna 1 quando extraiu uma linha, 0 quando ainda não tem linha.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">framer_try_get_line</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                               </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Copia com proteção */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">space</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">space</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* Política simples: reset (em produção: desconectar cliente) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Procura delimitador */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #88C0D0">memchr</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">nl</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* inclui &#39;\n&#39; */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out_line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* Remove a linha do buffer (shift) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memmove</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">remaining</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Uso típico no loop do socket: você chama <code>recv()</code>, joga os bytes no framer e enquanto ele conseguir extrair linhas você envia para a fila (<code>rxQueue</code>).</p>



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



<h4 class="wp-block-heading"><strong>8.2 Framing por header com tamanho (length-prefix)</strong></h4>



<p>Esse é o padrão de protocolos binários robustos. Você define, por exemplo:</p>



<ul class="wp-block-list">
<li>2 bytes: <code>len</code> (big-endian)</li>



<li><code>len</code> bytes: payload</li>
</ul>



<p>Vantagem: não depende de delimitador e funciona bem com binário. Desvantagem: você precisa validar tamanho, lidar com endianess e limites.</p>



<p>Estrutura de parsing por estados:</p>



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

#define MAX_FRAME 512

typedef enum { ST_LEN1, ST_LEN2, ST_PAYLOAD } ParseState_t;

typedef struct
{
    ParseState_t st;
    uint16_t expected;
    uint16_t got;
    uint8_t payload&#91;MAX_FRAME&#93;;
} LenFramer_t;

static void lenframer_init(LenFramer_t *f)
{
    f->st = ST_LEN1;
    f->expected = 0;
    f->got = 0;
}

/**
 * @brief Consome bytes e extrai frames completos. Retorna 1 quando extrai um frame.
 */
static int lenframer_feed(LenFramer_t *f, const uint8_t *data, uint16_t len,
                          uint8_t *out_payload, uint16_t *out_len)
{
    for (uint16_t i = 0; i &lt; len; i++)
    {
        uint8_t b = data&#91;i&#93;;

        switch (f->st)
        {
            case ST_LEN1:
                f->expected = ((uint16_t)b) &lt;&lt; 8;
                f->st = ST_LEN2;
                break;

            case ST_LEN2:
                f->expected |= b;
                if (f->expected == 0 || f->expected > MAX_FRAME) {
                    /* Frame inválido: reset (em produção: desconectar) */
                    lenframer_init(f);
                    break;
                }
                f->got = 0;
                f->st = ST_PAYLOAD;
                break;

            case ST_PAYLOAD:
                f->payload&#91;f->got++&#93; = b;
                if (f->got >= f->expected) {
                    memcpy(out_payload, f->payload, f->expected);
                    *out_len = f->expected;
                    lenframer_init(f);
                    return 1; /* extraiu 1 frame */
                }
                break;
        }
    }
    return 0;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">string</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">512</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParseState_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParseState_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">st</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">expected</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">got</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Consome bytes e extrai frames completos. Retorna 1 quando extrai um frame.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lenframer_feed</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LenFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">switch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN1</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> ((</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">b</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_LEN2</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MAX_FRAME</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #616E88">/* Frame inválido: reset (em produção: desconectar) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">st</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST_PAYLOAD</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">got</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">out_payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">payload</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">out_len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">expected</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #88C0D0">lenframer_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* extraiu 1 frame */</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Esse modelo é extremamente estável em ambiente real porque mantém o protocolo bem definido.</p>



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



<h4 class="wp-block-heading"><strong>8.3 Múltiplos clientes: duas arquiteturas</strong></h4>



<p>Agora vem o ponto de engenharia de firmware: <strong>como atender N conexões</strong> sem destruir RAM e sem perder previsibilidade.</p>



<p><strong>Opção A — Uma task por conexão (modelo simples)</strong></p>



<ul class="wp-block-list">
<li>Ao aceitar um cliente, você cria uma task dedicada para ele.</li>



<li>Cada task tem seu framer + buffer + loop <code>recv()</code>.</li>



<li>Fácil de entender e depurar.</li>



<li>Custo: cada task consome stack e TCB; em MCU pequeno isso vira limite rápido.</li>
</ul>



<p>Padrão típico:</p>



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

    for (;;)
    {
        uint8_t tmp&#91;128&#93;;
        int n = recv(client_fd, tmp, sizeof(tmp), 0);
        if (n &lt;= 0) break;

        uint8_t line&#91;LINE_BUF_SZ&#93;;
        uint16_t line_len;

        while (framer_try_get_line(&amp;fr, tmp, (uint16_t)n, line, &amp;line_len)) {
            /* aqui você empacota e manda para rxQueue */
        }
    }

    closesocket(client_fd);
    vTaskDelete(NULL);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">client_task</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">arg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">intptr_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">arg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">LineFramer_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fr</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">fr</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">128</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">recv</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tmp</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LINE_BUF_SZ</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line_len</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">framer_try_get_line</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">fr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tmp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">n</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">line</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">line_len</span><span style="color: #D8DEE9FF">)) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* aqui você empacota e manda para rxQueue */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">closesocket</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">client_fd</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vTaskDelete</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p><strong>Opção B — <code>select()</code> (modelo eficiente)</strong></p>



<ul class="wp-block-list">
<li>Uma única task monitora vários sockets ao mesmo tempo.</li>



<li>Melhor uso de RAM (uma task só), bom para dezenas de conexões.</li>



<li>Custo: mais complexo; exige tabela de conexões e estados por cliente.</li>
</ul>



<p>Se seu firmware precisa escalar, <code>select()</code> costuma ser o caminho. Se precisa ser simples e você terá poucos clientes, task por conexão é perfeito.</p>



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



<h4 class="wp-block-heading"><strong>8.4 Um detalhe que muita gente ignora: prioridade e latência</strong></h4>



<p>Não adianta ter framing perfeito se a task que atende sockets fica “no fim da fila” e perde janela TCP. Em geral, uma prática saudável é:</p>



<ul class="wp-block-list">
<li>TCP/IP thread: prioridade média-alta (depende do port e do vendor)</li>



<li>Gatekeeper de sockets: prioridade logo abaixo da TCP/IP thread</li>



<li>Workers de aplicação: prioridade média</li>



<li>Logs/telemetria: prioridade baixa</li>
</ul>



<p>Isso evita um cenário em que o processamento de aplicação “engole” a CPU e a rede degrada.</p>



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



<p>Na próxima seção, vamos fechar a arquitetura com os componentes que tornam isso resiliente em produto:</p>



<ul class="wp-block-list">
<li><strong>timeouts completos</strong> (recv/send/connect/accept)</li>



<li><strong>keepalive TCP</strong></li>



<li><strong>watchdog e task monitor aplicados ao domínio de rede</strong></li>



<li><strong>política de backpressure</strong> quando filas enchem</li>



<li>e um exemplo “quase HTTP” com parser mínimo</li>
</ul>



<h3 class="wp-block-heading"><strong>Robustez em rede: timeouts, keepalive, backpressure e integração com Task Monitor/Watchdog</strong></h3>



<p>Até aqui você já tem uma arquitetura correta. Agora entramos no que diferencia <strong>firmware de laboratório</strong> de <strong>firmware de campo</strong>: resiliência. Em sistemas FreeRTOS + lwIP, a maior parte das falhas em produção não vem de bugs óbvios, mas de <strong>bloqueios silenciosos</strong>, <strong>clientes mal-comportados</strong>, <strong>perda intermitente de link</strong>, <strong>filas saturadas</strong> e <strong>tarefas que parecem vivas, mas não fazem progresso</strong>. Esta seção trata exatamente desses pontos — com decisões práticas de engenharia.</p>



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



<h4 class="wp-block-heading"><strong>9.1 Timeouts em sockets: nunca confie em bloqueios infinitos</strong></h4>



<p>Chamadas como <code>accept()</code>, <code>recv()</code> e <code>send()</code> <strong>bloqueiam por padrão</strong>. Em firmware, isso é perigoso: se um cliente trava no meio de uma transmissão, sua task pode ficar presa indefinidamente, impedindo shutdown limpo, watchdog cooperativo e diagnóstico.</p>



<p>A regra é simples: <strong>todo socket deve ter timeout</strong>.</p>



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

    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &amp;tv, sizeof(tv));
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &amp;tv, sizeof(tv));
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">socket_set_timeouts</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sec</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">timeval</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tv</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_sec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sec</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tv_usec</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_RCVTIMEO</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tv</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_SNDTIMEO</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">tv</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">tv</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Use isso logo após <code>accept()</code>:</p>



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



<p>Com isso:</p>



<ul class="wp-block-list">
<li><code>recv()</code> retorna <code>&lt; 0</code> após timeout</li>



<li>você pode <strong>encerrar a conexão</strong>, <strong>reavaliar estado</strong> ou <strong>alimentar watchdog</strong></li>



<li>evita tarefas “zumbis”</li>
</ul>



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



<h4 class="wp-block-heading"><strong>9.2 TCP Keepalive: detectando clientes mortos</strong></h4>



<p>Em redes reais, cliente pode cair sem fechar socket (queda de Wi-Fi, cabo puxado, crash). O TCP keepalive permite detectar isso.</p>



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

int idle = 10;    /* segundos ociosos antes do probe */
int interval = 5; /* intervalo entre probes */
int count = 3;    /* probes antes de declarar morto */

setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &amp;idle, sizeof(idle));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &amp;interval, sizeof(interval));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &amp;count, sizeof(count));
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enable</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SOL_SOCKET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SO_KEEPALIVE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">enable</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">enable</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">idle</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* segundos ociosos antes do probe */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">interval</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* intervalo entre probes */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">count</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* probes antes de declarar morto */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPIDLE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">idle</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">idle</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPINTVL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">interval</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">interval</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">setsockopt</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">fd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IPPROTO_TCP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TCP_KEEPCNT</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">count</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">count</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p>Nem todos os ports do lwIP suportam todas essas opções, mas quando disponíveis, <strong>reduzem drasticamente conexões zumbis</strong>.</p>



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



<h4 class="wp-block-heading"><strong>9.3 Backpressure: o que fazer quando as filas enchem</strong></h4>



<p>Esse ponto é crítico e raramente tratado em exemplos. Se sua <code>rxQueue</code> enche, <strong>o sistema está dizendo que não consegue processar dados na mesma taxa em que recebe</strong>. Ignorar isso leva a latência crescente e colapso.</p>



<p>Existem quatro políticas clássicas:</p>



<ol class="wp-block-list">
<li><strong>Descartar mensagens novas</strong><br>Simples, mas pode quebrar protocolo.</li>



<li><strong>Bloquear o Gatekeeper por tempo limitado</strong><code>if (xQueueSend(rxQueue, &amp;msg, pdMS_TO_TICKS(50)) != pdPASS) { /* timeout: decide política */ }</code></li>



<li><strong>Parar de ler do socket temporariamente</strong><br>Com timeout em <code>recv()</code>, você simplesmente não chama <code>recv</code> por um ciclo.</li>



<li><strong>Desconectar cliente agressivo</strong> (muito comum em produto)<br>Se um cliente gera backpressure constante, ele é o problema.</li>
</ol>



<p>Em firmware sério, a política 4 costuma ser a mais segura.</p>



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



<h4 class="wp-block-heading"><strong>9.4 Integração com Task Monitor: detectar “tarefas vivas porém travadas”</strong></h4>



<p>Uma task bloqueada em <code>recv()</code> <strong>não parece travada</strong> para o scheduler — ela está em estado <em>Blocked</em>. Por isso, Task Monitor precisa ir além de “task rodando ou não”: precisa verificar <strong>progresso lógico</strong>.</p>



<p>Modelo simples: <em>heartbeat por domínio</em>.</p>



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

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



<p>O Task Monitor verifica:</p>



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

void task_monitor(void)
{
    if (net_heartbeat == last_net_hb) {
        /* rede não progrediu */
        /* ação: reiniciar task, reiniciar interface, logar */
    }
    last_net_hb = net_heartbeat;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">task_monitor</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* rede não progrediu */</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">/* ação: reiniciar task, reiniciar interface, logar */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">last_net_hb</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">net_heartbeat</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Isso detecta:</p>



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



<li>starvation</li>



<li>loops bloqueados por erro lógico</li>
</ul>



<p>Muito mais eficaz que apenas checar se a task existe.</p>



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



<h4 class="wp-block-heading"><strong>9.5 Watchdog cooperativo aplicado à rede</strong></h4>



<p>Nunca alimente o watchdog <strong>dentro da task de sockets diretamente</strong>. Isso mascara falhas. O correto é:</p>



<ul class="wp-block-list">
<li>task de rede atualiza estado/heartbeat</li>



<li><strong>task de supervisão</strong> decide se o sistema está saudável</li>



<li>só ela alimenta o watchdog</li>
</ul>



<p>Exemplo conceitual:</p>



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



<p>Assim, falhas de rede <strong>resetam o sistema</strong>, em vez de ficarem ocultas.</p>



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



<h4 class="wp-block-heading"><strong>9.6 Mini-HTTP: aplicação prática dos conceitos</strong></h4>



<p>Para fechar, um exemplo conceitual de servidor estilo HTTP minimalista:</p>



<ul class="wp-block-list">
<li>framing por <code>\r\n\r\n</code></li>



<li>timeout curto</li>



<li>parsing mínimo</li>



<li>resposta fixa</li>
</ul>



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



<p>Em firmware, <strong>HTTP raramente precisa ser completo</strong>. Muitas vezes é só um protocolo humano para debug, status e configuração inicial. Quanto mais simples, mais confiável.</p><p>The post <a href="https://mcu.tec.br/rtos/freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede/">FreeRTOS com lwIP: Arquitetura, Boas Práticas e Exemplos Reais de Sistemas Embarcados em Rede</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/freertos-com-lwip-arquitetura-boas-praticas-e-exemplos-reais-de-sistemas-embarcados-em-rede/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1082</post-id>	</item>
		<item>
		<title>FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</title>
		<link>https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freertos-uso-correto-de-queue-com-multiplos-consumidores</link>
					<comments>https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 27 Feb 2026 19:03:41 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[comunicação entre tarefas]]></category>
		<category><![CDATA[escalonador FreeRTOS]]></category>
		<category><![CDATA[event groups]]></category>
		<category><![CDATA[filas em RTOS]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[múltiplos consumidores]]></category>
		<category><![CDATA[queue FreeRTOS]]></category>
		<category><![CDATA[RTOS em microcontroladores]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[task notifications]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1059</guid>

					<description><![CDATA[<p>Aprenda como usar corretamente Queue com múltiplos consumidores no FreeRTOS. Entenda o impacto do escalonador, riscos de starvation, perda de eventos e quando usar alternativas como Event Groups e Task Notifications para criar firmwares robustos e previsíveis.</p>
<p>The post <a href="https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/">FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-gumxp wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-gumxp "><div class="eb-toc-container eb-toc-gumxp  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;text&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;text&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;text&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;text&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o: filas no FreeRTOS e o cen\u00e1rio de m\u00faltiplos consumidores&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-filas-no-freertos-e-o-cen\u00e1rio-de-m\u00faltiplos-consumidores&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelos cl\u00e1ssicos de m\u00faltiplos consumidores e o impacto no escalonador&quot;,&quot;value&quot;:&quot;modelos-cl\u00e1ssicos-de-m\u00faltiplos-consumidores-e-o-impacto-no-escalonador&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Cuidados essenciais e armadilhas comuns ao usar Queue com v\u00e1rios consumidores&quot;,&quot;value&quot;:&quot;cuidados-essenciais-e-armadilhas-comuns-ao-usar-queue-com-v\u00e1rios-consumidores&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Alternativas arquiteturais quando m\u00faltiplos consumidores precisam do mesmo evento&quot;,&quot;value&quot;:&quot;alternativas-arquiteturais-quando-m\u00faltiplos-consumidores-precisam-do-mesmo-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boas pr\u00e1ticas, diretrizes de projeto e fechamento&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-diretrizes-de-projeto-e-fechamento&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">Introdução: filas no FreeRTOS e o cenário de múltiplos consumidores</a><li><a href="#eb-table-content-1">Modelos clássicos de múltiplos consumidores e o impacto no escalonador</a><li><a href="#eb-table-content-2">Cuidados essenciais e armadilhas comuns ao usar Queue com vários consumidores</a><li><a href="#eb-table-content-3">Alternativas arquiteturais quando múltiplos consumidores precisam do mesmo evento</a><li><a href="#eb-table-content-4">Boas práticas, diretrizes de projeto e fechamento</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading">Introdução: filas no FreeRTOS e o cenário de múltiplos consumidores</h3>



<p>No FreeRTOS, <strong>Queue</strong> é um dos mecanismos centrais de comunicação e sincronização entre tarefas. Diferente de simples buffers, uma fila carrega não apenas dados, mas também <strong>semântica de sincronização</strong>, permitindo que tarefas produtoras e consumidoras operem de forma desacoplada no tempo. Em sistemas reais — especialmente em firmware para sensores, comunicação, aquisição de dados e pipelines de processamento — é muito comum termos <strong>um produtor e vários consumidores</strong>, todos interessados nos dados que chegam pela mesma fila.</p>



<p>O primeiro ponto importante, e frequentemente negligenciado, é que <strong>uma Queue do FreeRTOS não é um mecanismo de broadcast</strong>. Ela segue estritamente o modelo <em>FIFO</em> (First-In, First-Out) com <strong>remoção destrutiva do item</strong>. Isso significa que, quando múltiplas tarefas consumidoras bloqueiam na mesma fila, <strong>apenas uma delas receberá cada item enviado</strong>, e essa escolha é feita pelo escalonador com base em prioridade e estado das tarefas. Esse detalhe muda completamente a forma como o sistema deve ser arquitetado.</p>



<p>Esse comportamento é ideal quando os consumidores representam <strong>workers concorrentes</strong>, ou seja, tarefas equivalentes que disputam trabalho. Um exemplo clássico é um sistema em que uma interrupção de ADC empilha amostras em uma fila, e várias tarefas de processamento estatístico competem para consumir esses dados. Nesse caso, a fila atua como um <em>work queue</em>, balanceando carga automaticamente entre os consumidores.</p>



<p>Por outro lado, quando o objetivo é que <strong>todos os consumidores vejam todos os eventos</strong>, a Queue isoladamente é a escolha errada. Muitos bugs em sistemas embarcados com FreeRTOS surgem exatamente desse equívoco conceitual: o desenvolvedor assume que várias tarefas “escutando” a mesma fila receberão as mesmas mensagens, o que simplesmente não acontece. Esse erro se manifesta como perda intermitente de eventos, estados inconsistentes e falhas difíceis de reproduzir.</p>



<p>Para ilustrar o cenário correto de múltiplos consumidores concorrentes, considere o exemplo abaixo, onde várias tarefas processam mensagens vindas de um único produtor:</p>



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

QueueHandle_t xQueue;

void vProducerTask(void *pvParameters)
{
    message_t msg;
    uint32_t counter = 0;

    for (;;)
    {
        msg.id = counter++;
        msg.value = counter * 10;

        xQueueSend(xQueue, &amp;msg, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void vConsumerTask(void *pvParameters)
{
    message_t msg;

    for (;;)
    {
        if (xQueueReceive(xQueue, &amp;msg, portMAX_DELAY) == pdPASS)
        {
            /* Cada mensagem será processada por APENAS um consumidor */
            process_message(&amp;msg);
        }
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">id</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">message_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vProducerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">message_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">id</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">counter</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">vTaskDelay</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">pdMS_TO_TICKS</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">vConsumerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pvParameters</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">message_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdPASS</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #616E88">/* Cada mensagem será processada por APENAS um consumidor */</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">process_message</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p>Nesse modelo, várias instâncias de <code>vConsumerTask</code> podem ser criadas, e cada mensagem enviada pelo produtor será entregue a apenas uma delas. O FreeRTOS garante exclusão mútua implícita no acesso à fila, evitando a necessidade de mutex para esse fluxo específico.</p>



<p>Nesta artigo, vamos aprofundar <strong>quando esse modelo é ideal</strong>, <strong>quais implicações surgem em termos de escalonamento, prioridade e starvation</strong>, <strong>como evitar armadilhas comuns</strong>, e <strong>quais alternativas arquiteturais devem ser usadas quando o requisito é difusão (fan-out) e não competição</strong>.</p><p>The post <a href="https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/">FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/freertos-uso-correto-de-queue-com-multiplos-consumidores/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1059</post-id>	</item>
		<item>
		<title>Containerização em Sistemas Embarcados com Zephyr OS</title>
		<link>https://mcu.tec.br/rtos/containerizacao-em-sistemas-embarcados-com-zephyr-os/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=containerizacao-em-sistemas-embarcados-com-zephyr-os</link>
					<comments>https://mcu.tec.br/rtos/containerizacao-em-sistemas-embarcados-com-zephyr-os/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Wed, 25 Feb 2026 17:20:40 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura embarcada segura]]></category>
		<category><![CDATA[containerização no Zephyr OS]]></category>
		<category><![CDATA[containers embarcados]]></category>
		<category><![CDATA[domínios de memória RTOS]]></category>
		<category><![CDATA[firmware modular]]></category>
		<category><![CDATA[isolamento de aplicações em microcontroladores]]></category>
		<category><![CDATA[MPU em Cortex-M]]></category>
		<category><![CDATA[segurança em IoT]]></category>
		<category><![CDATA[userspace Zephyr]]></category>
		<category><![CDATA[Zephyr RTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1386</guid>

					<description><![CDATA[<p>Entenda como funciona a containerização no Zephyr OS e como o conceito de containers foi adaptado para sistemas embarcados e dispositivos IoT. Descubra como o Zephyr implementa isolamento de aplicações utilizando MPU, separação entre kernel e user space, domínios de memória e arquitetura multi-image. Saiba quais são as diferenças em relação ao Docker tradicional, os desafios em microcontroladores sem MMU e os benefícios para segurança, modularidade e atualizações OTA. Um guia técnico detalhado para engenheiros que desejam evoluir de firmware monolítico para arquiteturas embarcadas compartimentadas e mais seguras.</p>
<p>The post <a href="https://mcu.tec.br/rtos/containerizacao-em-sistemas-embarcados-com-zephyr-os/">Containerização em Sistemas Embarcados com Zephyr OS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introdução</h2>



<p>Durante muitos anos, a ideia de containerização esteve restrita ao universo de servidores e computação em nuvem. Tecnologias como Docker revolucionaram a forma como aplicações são distribuídas, implantadas e isoladas em ambientes Linux, permitindo que sistemas complexos fossem divididos em componentes independentes, seguros e facilmente atualizáveis. Entretanto, à medida que dispositivos IoT passaram a assumir funções críticas — desde gateways industriais até dispositivos médicos e infraestrutura conectada — surgiu uma necessidade semelhante no mundo dos sistemas embarcados: como isolar aplicações, garantir segurança e permitir atualizações modulares em microcontroladores com recursos limitados?</p>



<p>É nesse contexto que surge a evolução do conceito de containerização aplicada ao Zephyr, um sistema operacional de tempo real (RTOS) amplamente utilizado em dispositivos IoT e aplicações embarcadas. Diferentemente do modelo tradicional baseado em kernel Linux, hypervisors e virtualização pesada, a abordagem embarcada exige um redesenho do conceito de container para se adequar a arquiteturas com pouca memória, ausência de MMU (Memory Management Unit) e requisitos rígidos de determinismo temporal.</p>



<p>Este artigo explora como a containerização funciona no Zephyr OS, quais mecanismos tornam isso possível e quais são as implicações arquiteturais dessa nova abordagem para firmware moderno.</p>



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



<h2 class="wp-block-heading">O Conceito Original de Containerização</h2>



<p>No ambiente Linux tradicional, containerização consiste em empacotar uma aplicação juntamente com todas as suas dependências em uma unidade isolada chamada container. Diferente de uma máquina virtual, que executa um sistema operacional completo sobre um hypervisor, o container compartilha o kernel do sistema hospedeiro, isolando apenas o espaço de usuário.</p>



<p>Esse isolamento é obtido por meio de mecanismos como namespaces (isolamento de processos, rede e sistema de arquivos) e cgroups (controle de uso de CPU e memória). O resultado é um ambiente leve, eficiente e altamente portátil. Uma aplicação pode ser executada da mesma forma em diferentes máquinas, desde que o runtime de container esteja presente.</p>



<p>Contudo, esse modelo depende fortemente de características típicas de sistemas Linux completos, como suporte a virtualização, gerenciamento avançado de memória e separação robusta entre kernel e espaço de usuário. Em microcontroladores, esse cenário é completamente diferente.</p>



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



<h2 class="wp-block-heading">O Desafio da Containerização em Microcontroladores</h2>



<p>Em sistemas embarcados baseados em microcontroladores — como aqueles da família Cortex-M, ESP32 ou RP2040 — frequentemente não há suporte a MMU, e muitas vezes o sistema roda em modo bare-metal ou com um RTOS enxuto. A memória é limitada, e o firmware tradicionalmente é monolítico: todas as funcionalidades são compiladas juntas em uma única imagem binária.</p>



<p>Nesse modelo tradicional, um erro em qualquer parte do firmware pode comprometer todo o sistema. Não há isolamento real entre módulos, nem separação de privilégios. Isso se torna particularmente problemático quando o dispositivo precisa executar múltiplas aplicações, receber atualizações OTA (Over-The-Air) ou rodar código de terceiros.</p>



<p>O que o Zephyr propõe é uma adaptação do conceito de containerização para esse contexto restrito, utilizando os recursos disponíveis no hardware embarcado.</p>



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



<h2 class="wp-block-heading">Como o Zephyr Implementa Containerização</h2>



<p>A containerização no Zephyr não utiliza virtualização nem hypervisor. Em vez disso, ela se apoia em três pilares fundamentais:</p>



<ol class="wp-block-list">
<li>Separação entre kernel e espaço de usuário</li>



<li>Uso de MPU (Memory Protection Unit) quando disponível</li>



<li>Definição de domínios de memória e permissões de acesso</li>
</ol>



<p>O Zephyr permite que threads sejam executadas em modo usuário. Nessas condições, o acesso à memória e a periféricos é controlado pelo kernel. Cada aplicação pode ser associada a um domínio de memória específico, contendo apenas as regiões às quais ela tem permissão de acesso. Caso uma thread tente acessar uma região não autorizada, uma exceção é gerada.</p>



<p>Esse mecanismo cria uma forma de sandboxing embarcado. Embora não seja um container Linux no sentido tradicional, ele oferece isolamento suficiente para impedir que falhas em um módulo comprometam o restante do sistema.</p>



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



<h2 class="wp-block-heading">Domínios de Memória e Isolamento</h2>



<p>O conceito central por trás da containerização no Zephyr é o de memory domains. Um domínio de memória define um conjunto de regiões que uma aplicação pode acessar. Essas regiões podem incluir:</p>



<ul class="wp-block-list">
<li>Segmentos de código</li>



<li>Buffers de dados</li>



<li>Pilhas (stacks)</li>



<li>Heaps específicos</li>



<li>Áreas compartilhadas controladas</li>
</ul>



<p>Quando a MPU está presente, o hardware impõe essas restrições fisicamente. Isso garante que uma aplicação não consiga acessar memória pertencente a outra aplicação ou ao kernel.</p>



<p>Essa abordagem transforma o firmware monolítico tradicional em uma arquitetura modular compartimentada. Cada módulo passa a operar como se estivesse dentro de seu próprio container lógico.</p>



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



<h2 class="wp-block-heading">Multi-Image e Atualizações Modulares</h2>



<p>Outra característica importante é a possibilidade de trabalhar com múltiplas imagens de firmware. Em arquiteturas mais avançadas, como aquelas com bootloaders seguros e suporte a atualização OTA, diferentes componentes podem ser atualizados independentemente.</p>



<p>Esse modelo se aproxima ainda mais da filosofia de containerização moderna: componentes independentes, versionáveis e substituíveis sem necessidade de reconstruir todo o sistema.</p>



<p>Para dispositivos IoT conectados à nuvem, essa capacidade é estratégica. Ela permite corrigir vulnerabilidades específicas sem interromper todo o sistema, além de viabilizar aplicações de terceiros com maior segurança.</p>



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



<h2 class="wp-block-heading">Diferenças Fundamentais em Relação ao Docker</h2>



<p>É importante enfatizar que a containerização no Zephyr não executa Docker dentro do microcontrolador. Não há suporte a namespaces Linux nem gerenciamento de imagens no formato tradicional.</p>



<p>O que existe é uma implementação conceitual do isolamento, baseada em recursos de hardware embarcado. A proteção depende da MPU e da arquitetura do microcontrolador. Em dispositivos sem suporte a proteção de memória, o nível de isolamento é limitado.</p>



<p>Portanto, trata-se de uma adaptação do paradigma, e não de uma replicação direta da tecnologia de containers usada em servidores.</p>



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



<h2 class="wp-block-heading">Impacto Arquitetural</h2>



<p>A introdução de containerização no contexto do Zephyr representa uma mudança significativa na forma como firmware embarcado é estruturado. Em vez de um único bloco de código com acesso irrestrito a todos os recursos, passa-se a um modelo de aplicações isoladas, com permissões explícitas e fronteiras bem definidas.</p>



<p>Isso aproxima sistemas embarcados do modelo cloud-native, onde aplicações são desacopladas, independentes e resilientes. Para aplicações industriais, médicas e de infraestrutura crítica, esse nível adicional de segurança e modularidade pode ser determinante.</p>



<p>Além disso, a abordagem fortalece a segurança cibernética em dispositivos IoT, mitigando riscos associados a execução de código malicioso ou falhas não tratadas.</p>



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



<h2 class="wp-block-heading">Referências</h2>



<p>Electronic Design — “You Can Now Use Containers with Zephyr OS”<br><a href="https://www.electronicdesign.com/technologies/embedded/software/video/55355192/electronic-design-you-can-now-use-containers-with-zephyr-os">https://www.electronicdesign.com/technologies/embedded/software/video/55355192/electronic-design-you-can-now-use-containers-with-zephyr-os</a></p>



<p>Vídeo explicativo sobre containers no Zephyr OS<br><a href="https://www.youtube.com/watch?v=qqaKtV05NqA&amp;t=120s">https://www.youtube.com/watch?v=qqaKtV05NqA&amp;t=120s</a></p>



<p>Documentação oficial do Zephyr Project<br><a href="https://docs.zephyrproject.org/">https://docs.zephyrproject.org</a></p>



<p>Documentação do Docker<br><a href="https://docs.docker.com/">https://docs.docker.com</a></p><p>The post <a href="https://mcu.tec.br/rtos/containerizacao-em-sistemas-embarcados-com-zephyr-os/">Containerização em Sistemas Embarcados com Zephyr OS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/containerizacao-em-sistemas-embarcados-com-zephyr-os/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1386</post-id>	</item>
		<item>
		<title>Arquitetura Orientada a Eventos no FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arquitetura-orientada-a-eventos-no-freertos</link>
					<comments>https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 17:44:13 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[arquitetura orientada a eventos]]></category>
		<category><![CDATA[event groups]]></category>
		<category><![CDATA[filas FreeRTOS]]></category>
		<category><![CDATA[firmware reativo]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[message buffers]]></category>
		<category><![CDATA[programação em tempo real]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[sistemas determinísticos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[software timers]]></category>
		<category><![CDATA[stream buffers]]></category>
		<category><![CDATA[task notifications]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1057</guid>

					<description><![CDATA[<p>Meta descrição (≥ 600 caracteres):<br />
Este artigo apresenta uma abordagem técnica e didática sobre arquitetura orientada a eventos no FreeRTOS, explicando como projetar firmwares reativos, determinísticos e eficientes para sistemas embarcados. São analisados em profundidade os principais mecanismos do FreeRTOS, como Task Notifications, Event Groups, Queues, Stream Buffers, Message Buffers e Software Timers, sempre sob a ótica de engenharia de software embarcado. O texto demonstra como combinar corretamente esses mecanismos para evitar polling, reduzir consumo de CPU e energia, minimizar latência e melhorar a manutenção do código. Com exemplos práticos em C, análise de padrões arquiteturais e discussão dos erros mais comuns, o artigo serve como guia completo para desenvolvedores que desejam construir sistemas escaláveis, previsíveis e alinhados às melhores práticas de tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/">Arquitetura Orientada a Eventos no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-zyou1 wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-zyou1 "><div class="eb-toc-container eb-toc-zyou1  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;O que vem a seguir&quot;,&quot;text&quot;:&quot;O que vem a seguir&quot;,&quot;link&quot;:&quot;o-que-vem-a-seguir&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;text&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;link&quot;:&quot;modelo-conceitual-da-arquitetura-orientada-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;text&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;text&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;link&quot;:&quot;exemplo-conceitual-simplificado&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;text&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;text&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;link&quot;:&quot;task-notifications-como-mecanismo-central-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;text&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;link&quot;:&quot;modelo-mental-correto-para-task-notifications&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;link&quot;:&quot;exemplo-2-contador-de-eventos-acumulados&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;text&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;link&quot;:&quot;exemplo-3-task-notification-como-bitmap-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;text&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;link&quot;:&quot;vantagens-arquiteturais-das-task-notifications&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;text&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;text&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;link&quot;:&quot;modelo-de-uso-correto-para-event-groups&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Uso em ISRs&quot;,&quot;text&quot;:&quot;Uso em ISRs&quot;,&quot;link&quot;:&quot;uso-em-isrs&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;text&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;link&quot;:&quot;armadilhas-comuns-no-uso-de-event-groups&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;text&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;link&quot;:&quot;queues-e-message-passing-em-arquiteturas-orientadas-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;text&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;link&quot;:&quot;modelo-conceitual-de-filas-orientadas-a-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;link&quot;:&quot;exemplo-2-fila-como-buffer-de-desacoplamento&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;text&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;link&quot;:&quot;uso-combinado-queue-task-notification&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;text&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;text&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;link&quot;:&quot;stream-buffers-e-message-buffers-para-fluxos-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;text&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;link&quot;:&quot;exemplo-1-stream-buffer-com-uart&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;text&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;text&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;link&quot;:&quot;exemplo-2-message-buffer-para-comandos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;text&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilhas comuns&quot;,&quot;text&quot;:&quot;Armadilhas comuns&quot;,&quot;link&quot;:&quot;armadilhas-comuns&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;text&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;link&quot;:&quot;software-timers-como-geradores-de-eventos-temporais&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;text&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;link&quot;:&quot;modelo-conceitual-correto-para-software-timers&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;text&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;link&quot;:&quot;exemplo-1-timer-gerando-evento-simples&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;text&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;text&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;link&quot;:&quot;exemplo-3-timer-como-agendador-leve-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;text&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;link&quot;:&quot;prioridade-da-timer-service-task&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;text&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;text&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;text&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;text&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;text&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;link&quot;:&quot;eb-table-content-42&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;text&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;link&quot;:&quot;eb-table-content-43&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;text&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-44&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;text&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;link&quot;:&quot;eb-table-content-45&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;text&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;link&quot;:&quot;eb-table-content-46&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;text&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;link&quot;:&quot;eb-table-content-47&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;text&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;link&quot;:&quot;eb-table-content-48&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;text&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;link&quot;:&quot;erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;text&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;link&quot;:&quot;eb-table-content-50&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;text&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;link&quot;:&quot;erro-5-tasks-que-nunca-bloqueiam&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;text&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;link&quot;:&quot;erro-6-misturar-estado-e-evento&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;text&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;link&quot;:&quot;erro-7-overengineering-de-eventos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;text&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;link&quot;:&quot;eb-table-content-54&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;text&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;link&quot;:&quot;eb-table-content-55&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;text&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;link&quot;:&quot;eb-table-content-56&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;text&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;link&quot;:&quot;arquitetura-orientada-a-eventos-como-base-para-escalabilidade&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o e Motiva\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-e-motiva\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que vem a seguir&quot;,&quot;value&quot;:&quot;o-que-vem-a-seguir&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo Conceitual da Arquitetura Orientada a Eventos&quot;,&quot;value&quot;:&quot;modelo-conceitual-da-arquitetura-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Fluxo t\u00edpico de eventos no FreeRTOS&quot;,&quot;value&quot;:&quot;fluxo-t\u00edpico-de-eventos-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo conceitual simplificado&quot;,&quot;value&quot;:&quot;exemplo-conceitual-simplificado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implica\u00e7\u00f5es arquiteturais importantes&quot;,&quot;value&quot;:&quot;implica\u00e7\u00f5es-arquiteturais-importantes&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Task Notifications como Mecanismo Central de Eventos&quot;,&quot;value&quot;:&quot;task-notifications-como-mecanismo-central-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo mental correto para Task Notifications&quot;,&quot;value&quot;:&quot;modelo-mental-correto-para-task-notifications&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Evento simples (sinaliza\u00e7\u00e3o pura)&quot;,&quot;value&quot;:&quot;exemplo-1-evento-simples-sinaliza\u00e7\u00e3o-pura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Contador de eventos acumulados&quot;,&quot;value&quot;:&quot;exemplo-2-contador-de-eventos-acumulados&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 3 \u2014 Task Notification como bitmap de eventos&quot;,&quot;value&quot;:&quot;exemplo-3-task-notification-como-bitmap-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Vantagens arquiteturais das Task Notifications&quot;,&quot;value&quot;:&quot;vantagens-arquiteturais-das-task-notifications&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Event Groups: Coordena\u00e7\u00e3o de M\u00faltiplos Eventos&quot;,&quot;value&quot;:&quot;event-groups-coordena\u00e7\u00e3o-de-m\u00faltiplos-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo de uso correto para Event Groups&quot;,&quot;value&quot;:&quot;modelo-de-uso-correto-para-event-groups&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Aguardando m\u00faltiplos eventos simult\u00e2neos&quot;,&quot;value&quot;:&quot;exemplo-1-aguardando-m\u00faltiplos-eventos-simult\u00e2neos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Sinaliza\u00e7\u00e3o parcial e limpeza autom\u00e1tica&quot;,&quot;value&quot;:&quot;exemplo-2-sinaliza\u00e7\u00e3o-parcial-e-limpeza-autom\u00e1tica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso em ISRs&quot;,&quot;value&quot;:&quot;uso-em-isrs&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilhas comuns no uso de Event Groups&quot;,&quot;value&quot;:&quot;armadilhas-comuns-no-uso-de-event-groups&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Queues e Message Passing em Arquiteturas Orientadas a Eventos&quot;,&quot;value&quot;:&quot;queues-e-message-passing-em-arquiteturas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo conceitual de filas orientadas a eventos&quot;,&quot;value&quot;:&quot;modelo-conceitual-de-filas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Evento com payload (ISR \u2192 Task)&quot;,&quot;value&quot;:&quot;exemplo-1-evento-com-payload-isr-\u2192-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Fila como buffer de desacoplamento&quot;,&quot;value&quot;:&quot;exemplo-2-fila-como-buffer-de-desacoplamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Uso combinado: Queue + Task Notification&quot;,&quot;value&quot;:&quot;uso-combinado-queue-task-notification&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Implica\u00e7\u00f5es de projeto e dimensionamento&quot;,&quot;value&quot;:&quot;implica\u00e7\u00f5es-de-projeto-e-dimensionamento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers e Message Buffers para Fluxos de Eventos&quot;,&quot;value&quot;:&quot;stream-buffers-e-message-buffers-para-fluxos-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers \u2014 Eventos como fluxo cont\u00ednuo&quot;,&quot;value&quot;:&quot;stream-buffers-eventos-como-fluxo-cont\u00ednuo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Stream Buffer com UART&quot;,&quot;value&quot;:&quot;exemplo-1-stream-buffer-com-uart&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Thresholds e controle de lat\u00eancia&quot;,&quot;value&quot;:&quot;thresholds-e-controle-de-lat\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Message Buffers \u2014 Eventos com mensagens vari\u00e1veis&quot;,&quot;value&quot;:&quot;message-buffers-eventos-com-mensagens-vari\u00e1veis&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Message Buffer para comandos&quot;,&quot;value&quot;:&quot;exemplo-2-message-buffer-para-comandos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Compara\u00e7\u00e3o arquitetural&quot;,&quot;value&quot;:&quot;compara\u00e7\u00e3o-arquitetural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilhas comuns&quot;,&quot;value&quot;:&quot;armadilhas-comuns&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Software Timers como Geradores de Eventos Temporais&quot;,&quot;value&quot;:&quot;software-timers-como-geradores-de-eventos-temporais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Modelo conceitual correto para Software Timers&quot;,&quot;value&quot;:&quot;modelo-conceitual-correto-para-software-timers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 1 \u2014 Timer gerando evento simples&quot;,&quot;value&quot;:&quot;exemplo-1-timer-gerando-evento-simples&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 2 \u2014 Timer peri\u00f3dico como evento de sistema&quot;,&quot;value&quot;:&quot;exemplo-2-timer-peri\u00f3dico-como-evento-de-sistema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo 3 \u2014 Timer como agendador leve de eventos&quot;,&quot;value&quot;:&quot;exemplo-3-timer-como-agendador-leve-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Prioridade da Timer Service Task&quot;,&quot;value&quot;:&quot;prioridade-da-timer-service-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Integra\u00e7\u00e3o com arquiteturas orientadas a eventos&quot;,&quot;value&quot;:&quot;integra\u00e7\u00e3o-com-arquiteturas-orientadas-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Composi\u00e7\u00e3o Arquitetural de Eventos no FreeRTOS&quot;,&quot;value&quot;:&quot;composi\u00e7\u00e3o-arquitetural-de-eventos-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 1 \u2014 ISR m\u00ednima + Evento Direcionado&quot;,&quot;value&quot;:&quot;padr\u00e3o-1-isr-m\u00ednima-evento-direcionado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 2 \u2014 Evento acorda, fila transporta&quot;,&quot;value&quot;:&quot;padr\u00e3o-2-evento-acorda-fila-transporta&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 3 \u2014 Event Group como estado global, n\u00e3o evento&quot;,&quot;value&quot;:&quot;padr\u00e3o-3-event-group-como-estado-global-n\u00e3o-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 4 \u2014 Timer \u2192 Evento \u2192 Task&quot;,&quot;value&quot;:&quot;padr\u00e3o-4-timer-\u2192-evento-\u2192-task&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00e3o 5 \u2014 M\u00e1quina de estados orientada a eventos&quot;,&quot;value&quot;:&quot;padr\u00e3o-5-m\u00e1quina-de-estados-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Princ\u00edpios arquiteturais que emergem&quot;,&quot;value&quot;:&quot;princ\u00edpios-arquiteturais-que-emergem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erros Arquiteturais Comuns e Como Evit\u00e1-los&quot;,&quot;value&quot;:&quot;erros-arquiteturais-comuns-e-como-evit\u00e1-los&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 1 \u2014 Polling disfar\u00e7ado de arquitetura orientada a eventos&quot;,&quot;value&quot;:&quot;erro-1-polling-disfar\u00e7ado-de-arquitetura-orientada-a-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 2 \u2014 L\u00f3gica pesada dentro de ISRs&quot;,&quot;value&quot;:&quot;erro-2-l\u00f3gica-pesada-dentro-de-isrs&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 3 \u2014 Uso excessivo de Event Groups como fila de eventos&quot;,&quot;value&quot;:&quot;erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 4 \u2014 Fila gen\u00e9rica para tudo&quot;,&quot;value&quot;:&quot;erro-4-fila-gen\u00e9rica-para-tudo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 5 \u2014 Tasks que nunca bloqueiam&quot;,&quot;value&quot;:&quot;erro-5-tasks-que-nunca-bloqueiam&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 6 \u2014 Misturar estado e evento&quot;,&quot;value&quot;:&quot;erro-6-misturar-estado-e-evento&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Erro 7 \u2014 Overengineering de eventos&quot;,&quot;value&quot;:&quot;erro-7-overengineering-de-eventos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Checklist arquitetural pr\u00e1tico&quot;,&quot;value&quot;:&quot;checklist-arquitetural-pr\u00e1tico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o T\u00e9cnica, Boas Pr\u00e1ticas e Impacto no Projeto&quot;,&quot;value&quot;:&quot;conclus\u00e3o-t\u00e9cnica-boas-pr\u00e1ticas-e-impacto-no-projeto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boas pr\u00e1ticas consolidadas&quot;,&quot;value&quot;:&quot;boas-pr\u00e1ticas-consolidadas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Arquitetura orientada a eventos como base para escalabilidade&quot;,&quot;value&quot;:&quot;arquitetura-orientada-a-eventos-como-base-para-escalabilidade&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">Introdução e Motivação</a><li><a href="#o-que-vem-a-seguir">O que vem a seguir</a><li><a href="#modelo-conceitual-da-arquitetura-orientada-a-eventos">Modelo Conceitual da Arquitetura Orientada a Eventos</a><li><a href="#eb-table-content-3">Fluxo típico de eventos no FreeRTOS</a><li><a href="#exemplo-conceitual-simplificado">Exemplo conceitual simplificado</a><li><a href="#eb-table-content-5">Implicações arquiteturais importantes</a><li><a href="#task-notifications-como-mecanismo-central-de-eventos">Task Notifications como Mecanismo Central de Eventos</a><li><a href="#modelo-mental-correto-para-task-notifications">Modelo mental correto para Task Notifications</a><li><a href="#eb-table-content-8">Exemplo 1 — Evento simples (sinalização pura)</a><li><a href="#exemplo-2-contador-de-eventos-acumulados">Exemplo 2 — Contador de eventos acumulados</a><li><a href="#exemplo-3-task-notification-como-bitmap-de-eventos">Exemplo 3 — Task Notification como bitmap de eventos</a><li><a href="#vantagens-arquiteturais-das-task-notifications">Vantagens arquiteturais das Task Notifications</a><li><a href="#eb-table-content-12">Event Groups: Coordenação de Múltiplos Eventos</a><li><a href="#modelo-de-uso-correto-para-event-groups">Modelo de uso correto para Event Groups</a><li><a href="#eb-table-content-14">Exemplo 1 — Aguardando múltiplos eventos simultâneos</a><li><a href="#eb-table-content-15">Exemplo 2 — Sinalização parcial e limpeza automática</a><li><a href="#uso-em-isrs">Uso em ISRs</a><li><a href="#armadilhas-comuns-no-uso-de-event-groups">Armadilhas comuns no uso de Event Groups</a><li><a href="#queues-e-message-passing-em-arquiteturas-orientadas-a-eventos">Queues e Message Passing em Arquiteturas Orientadas a Eventos</a><li><a href="#modelo-conceitual-de-filas-orientadas-a-eventos">Modelo conceitual de filas orientadas a eventos</a><li><a href="#eb-table-content-20">Exemplo 1 — Evento com payload (ISR → Task)</a><li><a href="#exemplo-2-fila-como-buffer-de-desacoplamento">Exemplo 2 — Fila como buffer de desacoplamento</a><li><a href="#uso-combinado-queue-task-notification">Uso combinado: Queue + Task Notification</a><li><a href="#eb-table-content-23">Implicações de projeto e dimensionamento</a><li><a href="#stream-buffers-e-message-buffers-para-fluxos-de-eventos">Stream Buffers e Message Buffers para Fluxos de Eventos</a><li><a href="#eb-table-content-25">Stream Buffers — Eventos como fluxo contínuo</a><li><a href="#exemplo-1-stream-buffer-com-uart">Exemplo 1 — Stream Buffer com UART</a><li><a href="#eb-table-content-27">Thresholds e controle de latência</a><li><a href="#eb-table-content-28">Message Buffers — Eventos com mensagens variáveis</a><li><a href="#exemplo-2-message-buffer-para-comandos">Exemplo 2 — Message Buffer para comandos</a><li><a href="#eb-table-content-30">Comparação arquitetural</a><li><a href="#armadilhas-comuns">Armadilhas comuns</a><li><a href="#software-timers-como-geradores-de-eventos-temporais">Software Timers como Geradores de Eventos Temporais</a><li><a href="#modelo-conceitual-correto-para-software-timers">Modelo conceitual correto para Software Timers</a><li><a href="#exemplo-1-timer-gerando-evento-simples">Exemplo 1 — Timer gerando evento simples</a><li><a href="#eb-table-content-35">Exemplo 2 — Timer periódico como evento de sistema</a><li><a href="#exemplo-3-timer-como-agendador-leve-de-eventos">Exemplo 3 — Timer como agendador leve de eventos</a><li><a href="#prioridade-da-timer-service-task">Prioridade da Timer Service Task</a><li><a href="#eb-table-content-38">Integração com arquiteturas orientadas a eventos</a><li><a href="#eb-table-content-39">Composição Arquitetural de Eventos no FreeRTOS</a><li><a href="#eb-table-content-40">Padrão 1 — ISR mínima + Evento Direcionado</a><li><a href="#eb-table-content-41">Padrão 2 — Evento acorda, fila transporta</a><li><a href="#eb-table-content-42">Padrão 3 — Event Group como estado global, não evento</a><li><a href="#eb-table-content-43">Padrão 4 — Timer → Evento → Task</a><li><a href="#eb-table-content-44">Padrão 5 — Máquina de estados orientada a eventos</a><li><a href="#eb-table-content-45">Princípios arquiteturais que emergem</a><li><a href="#eb-table-content-46">Erros Arquiteturais Comuns e Como Evitá-los</a><li><a href="#eb-table-content-47">Erro 1 — Polling disfarçado de arquitetura orientada a eventos</a><li><a href="#eb-table-content-48">Erro 2 — Lógica pesada dentro de ISRs</a><li><a href="#erro-3-uso-excessivo-de-event-groups-como-fila-de-eventos">Erro 3 — Uso excessivo de Event Groups como fila de eventos</a><li><a href="#eb-table-content-50">Erro 4 — Fila genérica para tudo</a><li><a href="#erro-5-tasks-que-nunca-bloqueiam">Erro 5 — Tasks que nunca bloqueiam</a><li><a href="#erro-6-misturar-estado-e-evento">Erro 6 — Misturar estado e evento</a><li><a href="#erro-7-overengineering-de-eventos">Erro 7 — Overengineering de eventos</a><li><a href="#eb-table-content-54">Checklist arquitetural prático</a><li><a href="#eb-table-content-55">Conclusão Técnica, Boas Práticas e Impacto no Projeto</a><li><a href="#eb-table-content-56">Boas práticas consolidadas</a><li><a href="#arquitetura-orientada-a-eventos-como-base-para-escalabilidade">Arquitetura orientada a eventos como base para escalabilidade</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading"><strong>Introdução e Motivação</strong></h3>



<p>Em sistemas embarcados modernos, especialmente aqueles baseados em <strong>FreeRTOS</strong>, a forma como o firmware reage ao mundo externo é tão importante quanto o código em si. Sensores, comunicação, interrupções, timers e pilhas de protocolo geram estímulos de forma assíncrona, e arquiteturas tradicionais baseadas apenas em <em>superloop</em> rapidamente se tornam difíceis de manter, escalar e depurar. É nesse contexto que surge a <strong>Arquitetura Orientada a Eventos (Event-Driven Architecture – EDA)</strong>.</p>



<p>No FreeRTOS, uma arquitetura orientada a eventos não é um “modo especial” do sistema operacional, mas sim uma <strong>estratégia de organização do firmware</strong>, onde tarefas permanecem bloqueadas aguardando eventos específicos e acordam apenas quando algo relevante ocorre. Esses eventos podem ser sinais de interrupção, mensagens, flags, notificações, timers ou dados disponíveis em buffers. O resultado é um sistema <strong>reativo, determinístico e eficiente em consumo de CPU</strong>.</p>



<p>Do ponto de vista de engenharia, essa abordagem resolve três problemas clássicos:</p>



<ol class="wp-block-list">
<li><strong>Desperdício de CPU</strong> causado por polling constante</li>



<li><strong>Acoplamento excessivo</strong> entre módulos</li>



<li><strong>Dificuldade de sincronização</strong> entre múltiplas fontes de eventos</li>
</ol>



<p>Ao adotar uma arquitetura orientada a eventos, o firmware passa a se comportar como um <strong>conjunto de agentes cooperativos</strong>, cada tarefa com responsabilidade clara, reagindo apenas aos eventos que lhe dizem respeito. Isso melhora a legibilidade do código, reduz latência média de resposta e facilita testes unitários e manutenção evolutiva.</p>



<p>No FreeRTOS, essa arquitetura é viabilizada por um conjunto muito poderoso de primitivas nativas: <strong>Task Notifications</strong>, <strong>Queues</strong>, <strong>Event Groups</strong>, <strong>Stream Buffers</strong>, <strong>Message Buffers</strong> e <strong>Software Timers</strong>. Cada uma delas atende a um tipo específico de evento e será explorada detalhadamente ao longo deste artigo, sempre com exemplos práticos e contextualizados.</p>



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



<h3 class="wp-block-heading"><strong>O que vem a seguir</strong></h3>



<p>Na próxima seção, entraremos no <strong>modelo conceitual da Arquitetura Orientada a Eventos no FreeRTOS</strong>, explicando como eventos fluem pelo sistema, como tarefas devem ser estruturadas e como evitar armadilhas comuns, como <em>event storms</em>, inversão de prioridade e acoplamento indireto.</p>



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



<h3 class="wp-block-heading"><strong>Modelo Conceitual da Arquitetura Orientada a Eventos</strong></h3>



<p>Em uma arquitetura orientada a eventos no FreeRTOS, o sistema deixa de ser centrado em fluxo sequencial de execução e passa a ser organizado em torno de <strong>eventos que representam fatos relevantes do sistema</strong>. Um evento pode significar “um dado chegou”, “um tempo expirou”, “um periférico terminou uma operação” ou “uma condição de estado foi satisfeita”. O papel central do RTOS é <strong>suspender tarefas até que esses eventos ocorram</strong>, garantindo previsibilidade temporal e uso eficiente do processador.</p>



<p>Do ponto de vista conceitual, essa arquitetura pode ser dividida em três elementos fundamentais: <strong>produtores de eventos</strong>, <strong>mecanismos de transporte de eventos</strong> e <strong>consumidores de eventos</strong>. Produtores normalmente são ISRs, timers de software, drivers ou tarefas de baixo nível. O transporte é feito pelas primitivas do FreeRTOS, enquanto os consumidores são tarefas que encapsulam lógica de negócio ou processamento de dados. Esse desacoplamento é essencial para sistemas escaláveis.</p>



<p>Um princípio importante é que <strong>tarefas orientadas a eventos devem permanecer bloqueadas na maior parte do tempo</strong>. Em FreeRTOS, isso significa usar chamadas bloqueantes como <code>xQueueReceive()</code>, <code>xEventGroupWaitBits()</code> ou <code>ulTaskNotifyTake()</code>, sempre com <code>portMAX_DELAY</code> ou tempos bem definidos. Dessa forma, não há polling ativo, e o escalonador pode dedicar CPU apenas às tarefas que realmente precisam executar naquele instante.</p>



<p>Outro ponto crítico do modelo é que <strong>eventos não devem carregar lógica</strong>, apenas sinalização e dados mínimos. A decisão do que fazer em resposta a um evento pertence à tarefa consumidora. Isso evita que ISRs fiquem complexas e garante que decisões de alto nível ocorram sempre em contexto de tarefa, onde mutexes, alocação de memória e chamadas de API são seguras.</p>



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



<h3 class="wp-block-heading"><strong>Fluxo típico de eventos no FreeRTOS</strong></h3>



<p>Um fluxo clássico em arquitetura orientada a eventos segue o seguinte encadeamento lógico:</p>



<ol class="wp-block-list">
<li>Um periférico gera uma interrupção (por exemplo, UART RX completa).</li>



<li>A ISR sinaliza o evento usando uma primitiva segura para interrupções.</li>



<li>O kernel do FreeRTOS desbloqueia a tarefa interessada.</li>



<li>A tarefa acorda, processa o evento e retorna ao estado bloqueado.</li>
</ol>



<p>Esse modelo cria um sistema <strong>reativo e previsível</strong>, onde a latência entre o evento e o processamento é controlada diretamente pela prioridade da tarefa e pela duração das ISRs. Em projetos bem arquitetados, o tempo gasto dentro da interrupção é mínimo, e todo o processamento ocorre em nível de tarefa.</p>



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



<h3 class="wp-block-heading"><strong>Exemplo conceitual simplificado</strong></h3>



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

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



<p>Neste exemplo, a tarefa <code>vUartTask</code> não executa continuamente. Ela permanece bloqueada até que um byte seja colocado na fila por uma ISR ou outra tarefa. Isso caracteriza perfeitamente o modelo orientado a eventos: <strong>o evento é a chegada de um dado</strong>, e a tarefa existe apenas para reagir a ele.</p>



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



<h3 class="wp-block-heading"><strong>Implicações arquiteturais importantes</strong></h3>



<p>Ao adotar esse modelo, algumas decisões de projeto tornam-se fundamentais. A granularidade dos eventos deve ser cuidadosamente escolhida: eventos muito genéricos levam a tarefas complexas e difíceis de testar; eventos excessivamente específicos geram sobrecarga e fragmentação. Além disso, o uso correto de prioridades é crucial para garantir que eventos críticos sejam tratados com menor latência.</p>



<p>Outro aspecto frequentemente negligenciado é o tratamento de <strong>eventos concorrentes</strong>. O FreeRTOS permite que múltiplos eventos acordem a mesma tarefa, mas o firmware deve ser capaz de lidar com isso de forma determinística, normalmente utilizando estruturas de estado bem definidas ou <em>state machines</em> orientadas a eventos.</p>



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



<p>Na <strong>próxima seção</strong>, entraremos nos <strong>mecanismos de eventos disponíveis no FreeRTOS</strong>, começando pelo mais eficiente e subutilizado deles: <strong>Task Notifications</strong>, analisando seu funcionamento interno, vantagens, limitações e padrões de uso.</p>



<p>Excelente, seguimos.</p>



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



<h3 class="wp-block-heading"><strong>Task Notifications como Mecanismo Central de Eventos</strong></h3>



<p>Entre todos os mecanismos oferecidos pelo FreeRTOS, as <strong>Task Notifications</strong> são, do ponto de vista arquitetural, a forma mais eficiente de implementar uma arquitetura orientada a eventos. Elas funcionam como um <strong>canal direto ponto-a-ponto entre o kernel e uma tarefa</strong>, sem a sobrecarga de filas, sem alocação dinâmica e com latência mínima.</p>



<p>Cada tarefa no FreeRTOS possui internamente um <strong>array de notificações</strong> (desde o FreeRTOS 10), onde cada entrada contém um valor de 32 bits e um estado. Isso transforma a task notification em algo conceitualmente próximo a um <strong>registrador de eventos privado da tarefa</strong>. Esse detalhe é fundamental para entender por que esse mecanismo é tão eficiente e, ao mesmo tempo, tão poderoso.</p>



<p>Diferente de filas ou event groups, <strong>uma task notification não é compartilhada</strong>. Ela pertence a uma única tarefa. Isso força uma arquitetura mais limpa, onde existe um mapeamento explícito entre <em>quem produz</em> e <em>quem consome</em> o evento. Em arquiteturas bem desenhadas, isso reduz drasticamente o acoplamento implícito e elimina ambiguidades.</p>



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



<h3 class="wp-block-heading"><strong>Modelo mental correto para Task Notifications</strong></h3>



<p>É comum iniciantes tratarem task notifications como “um semáforo mais rápido”. Embora isso seja parcialmente verdadeiro, essa visão é limitada. O modelo correto é pensar nelas como:</p>



<ul class="wp-block-list">
<li>Um <strong>evento binário</strong> (acordar ou não acordar a task)</li>



<li>Um <strong>contador</strong> (quantidade de eventos acumulados)</li>



<li>Um <strong>bitmap de flags</strong></li>



<li>Um <strong>payload de 32 bits</strong></li>
</ul>



<p>Tudo isso usando a <strong>mesma infraestrutura</strong>, dependendo apenas da API utilizada.</p>



<p>Essa flexibilidade permite criar arquiteturas orientadas a eventos extremamente compactas, onde um único mecanismo substitui filas, semáforos e flags em muitos cenários.</p>



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



<h3 class="wp-block-heading"><strong>Exemplo 1 — Evento simples (sinalização pura)</strong></h3>



<p>Neste primeiro exemplo, uma ISR sinaliza que um evento ocorreu, e a tarefa apenas reage.</p>



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

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



<p>A função <code>ulTaskNotifyTake()</code> bloqueia a tarefa até que uma notificação seja recebida. O parâmetro <code>pdTRUE</code> indica que o contador interno será limpo ao acordar, garantindo comportamento de evento simples.</p>



<p>A ISR responsável pelo evento:</p>



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

    vTaskNotifyGiveFromISR(eventTaskHandle, &amp;xHigherPriorityTaskWoken);

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



<p>Aqui, o evento é produzido de forma segura em contexto de interrupção, e o kernel pode realizar <em>context switch</em> imediato se a prioridade justificar. Esse padrão é ideal para eventos como botão pressionado, fim de conversão ADC ou término de DMA.</p>



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



<h3 class="wp-block-heading"><strong>Exemplo 2 — Contador de eventos acumulados</strong></h3>



<p>Em cenários onde múltiplos eventos podem ocorrer antes da tarefa acordar, a task notification pode atuar como <strong>contador</strong>.</p>



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

    for (;;)
    {
        events = ulTaskNotifyTake(pdFALSE, portMAX_DELAY);

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



<p>Ao usar <code>pdFALSE</code>, o contador não é automaticamente zerado. O valor retornado indica quantos eventos ocorreram desde a última leitura. Isso é extremamente útil em sistemas com bursts de eventos, como recepção de pacotes ou amostras rápidas de sensores.</p>



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



<h3 class="wp-block-heading"><strong>Exemplo 3 — Task Notification como bitmap de eventos</strong></h3>



<p>Outra aplicação avançada é usar o valor de 32 bits como <strong>mapa de bits de eventos</strong>, substituindo completamente os Event Groups quando o evento é destinado a uma única tarefa.</p>



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

void vCommTask(void *pvParameters)
{
    uint32_t events;

    for (;;)
    {
        xTaskNotifyWait(0x00, 0xFFFFFFFF, &amp;events, portMAX_DELAY);

        if (events &amp; EVT_RX_READY)
            handleRx();

        if (events &amp; EVT_TX_DONE)
            handleTxDone();

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



<p>Esse padrão cria uma <strong>máquina de eventos compacta</strong>, extremamente eficiente e fácil de analisar em termos de latência e consumo de recursos.</p>



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



<h3 class="wp-block-heading"><strong>Vantagens arquiteturais das Task Notifications</strong></h3>



<p>Do ponto de vista de engenharia de sistemas, as task notifications oferecem:</p>



<ul class="wp-block-list">
<li>Menor latência entre evento e execução</li>



<li>Zero uso de heap</li>



<li>Menor footprint de memória</li>



<li>Determinismo temporal elevado</li>



<li>Código mais explícito e fácil de rastrear</li>
</ul>



<p>Por esse motivo, em arquiteturas orientadas a eventos bem projetadas, <strong>task notifications devem ser a primeira opção</strong>, e não a última.</p>



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



<p>Na <strong>próxima seção</strong>, vamos tratar de <strong>Event Groups</strong>, explicando quando eles são necessários, como evitá-los em excesso e como integrá-los corretamente em uma arquitetura orientada a eventos sem criar dependências implícitas.</p>



<p>Seguimos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/">Arquitetura Orientada a Eventos no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/arquitetura-orientada-a-eventos-no-freertos/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1057</post-id>	</item>
		<item>
		<title>FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</title>
		<link>https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha</link>
					<comments>https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/#respond</comments>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 13 Feb 2026 16:10:46 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[buffers circulares]]></category>
		<category><![CDATA[comunicação entre tarefas]]></category>
		<category><![CDATA[desempenho em tempo real]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[ISR FreeRTOS]]></category>
		<category><![CDATA[producer consumer]]></category>
		<category><![CDATA[queue FreeRTOS]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stream buffer]]></category>
		<category><![CDATA[UART FreeRTOS]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1050</guid>

					<description><![CDATA[<p>Neste artigo técnico e didático, exploramos em profundidade o uso de Stream Buffers no FreeRTOS, explicando seu funcionamento interno, comparando-os detalhadamente com Queues e apresentando critérios claros para escolher o mecanismo correto em sistemas embarcados. O conteúdo aborda desempenho, latência, uso de memória, topologia produtor–consumidor, boas práticas, armadilhas comuns e exemplos de código em C voltados a aplicações reais como UART, sensores e pipelines de dados em tempo real.</p>
<p>The post <a href="https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/">FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-x3mpg wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-x3mpg "><div class="eb-toc-container eb-toc-x3mpg  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemCollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:3,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;text&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;text&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;text&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;link&quot;:&quot;exemplo-de-escrita-em-uma-tarefa-produtora&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;text&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;link&quot;:&quot;exemplo-de-leitura-em-uma-tarefa-consumidora&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;text&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;link&quot;:&quot;queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;text&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Envio de dados para a Queue&quot;,&quot;text&quot;:&quot;Envio de dados para a Queue&quot;,&quot;link&quot;:&quot;envio-de-dados-para-a-queue&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;text&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Custos ocultos das Queues&quot;,&quot;text&quot;:&quot;Custos ocultos das Queues&quot;,&quot;link&quot;:&quot;custos-ocultos-das-queues&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;text&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;text&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;text&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;text&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;link&quot;:&quot;exemplo-comparativo-uart-rx&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;text&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;text&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;text&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;link&quot;:&quot;armadilha-1-tratar-stream-buffer-como-message-queue&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;text&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;text&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;link&quot;:&quot;armadilha-3-usar-delays-em-vez-de-bloqueio&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;text&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o: comunica\u00e7\u00e3o entre tarefas no FreeRTOS&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o-comunica\u00e7\u00e3o-entre-tarefas-no-freertos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;O que s\u00e3o Stream Buffers no FreeRTOS e como eles funcionam internamente&quot;,&quot;value&quot;:&quot;o-que-s\u00e3o-stream-buffers-no-freertos-e-como-eles-funcionam-internamente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de um Stream Buffer&quot;,&quot;value&quot;:&quot;exemplo-b\u00e1sico-cria\u00e7\u00e3o-de-um-stream-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de escrita em uma tarefa produtora&quot;,&quot;value&quot;:&quot;exemplo-de-escrita-em-uma-tarefa-produtora&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo de leitura em uma tarefa consumidora&quot;,&quot;value&quot;:&quot;exemplo-de-leitura-em-uma-tarefa-consumidora&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Queues no FreeRTOS: modelo de dados, garantias e custos ocultos&quot;,&quot;value&quot;:&quot;queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo b\u00e1sico: cria\u00e7\u00e3o de uma Queue&quot;,&quot;value&quot;:&quot;exemplo-b\u00e1sico-cria\u00e7\u00e3o-de-uma-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Envio de dados para a Queue&quot;,&quot;value&quot;:&quot;envio-de-dados-para-a-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Recep\u00e7\u00e3o de dados da Queue&quot;,&quot;value&quot;:&quot;recep\u00e7\u00e3o-de-dados-da-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Custos ocultos das Queues&quot;,&quot;value&quot;:&quot;custos-ocultos-das-queues&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Stream Buffers vs Queues: compara\u00e7\u00e3o t\u00e9cnica detalhada e crit\u00e9rios de escolha&quot;,&quot;value&quot;:&quot;stream-buffers-vs-queues-compara\u00e7\u00e3o-t\u00e9cnica-detalhada-e-crit\u00e9rios-de-escolha&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Compara\u00e7\u00e3o estrutural&quot;,&quot;value&quot;:&quot;compara\u00e7\u00e3o-estrutural&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 1: natureza do dado&quot;,&quot;value&quot;:&quot;crit\u00e9rio-1-natureza-do-dado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 2: desempenho e lat\u00eancia&quot;,&quot;value&quot;:&quot;crit\u00e9rio-2-desempenho-e-lat\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Crit\u00e9rio 3: topologia produtor\u2013consumidor&quot;,&quot;value&quot;:&quot;crit\u00e9rio-3-topologia-produtorconsumidor&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Exemplo comparativo: UART RX&quot;,&quot;value&quot;:&quot;exemplo-comparativo-uart-rx&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Padr\u00f5es de uso, boas pr\u00e1ticas e armadilhas comuns com Stream Buffers&quot;,&quot;value&quot;:&quot;padr\u00f5es-de-uso-boas-pr\u00e1ticas-e-armadilhas-comuns-com-stream-buffers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 1: dimensionamento correto do buffer&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-1-dimensionamento-correto-do-buffer&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 2: uso consciente do trigger level&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-2-uso-consciente-do-trigger-level&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Boa pr\u00e1tica 3: sempre respeitar o modelo 1\u21921&quot;,&quot;value&quot;:&quot;boa-pr\u00e1tica-3-sempre-respeitar-o-modelo-1\u21921&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 1: tratar Stream Buffer como Message Queue&quot;,&quot;value&quot;:&quot;armadilha-1-tratar-stream-buffer-como-message-queue&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 2: ignorar retornos das fun\u00e7\u00f5es&quot;,&quot;value&quot;:&quot;armadilha-2-ignorar-retornos-das-fun\u00e7\u00f5es&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Armadilha 3: usar delays em vez de bloqueio&quot;,&quot;value&quot;:&quot;armadilha-3-usar-delays-em-vez-de-bloqueio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Conclus\u00e3o t\u00e9cnica e diretrizes finais de projeto&quot;,&quot;value&quot;:&quot;conclus\u00e3o-t\u00e9cnica-e-diretrizes-finais-de-projeto&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class='eb-toc__list'><li><a href="#eb-table-content-0">Introdução: comunicação entre tarefas no FreeRTOS</a><li><a href="#eb-table-content-1">O que são Stream Buffers no FreeRTOS e como eles funcionam internamente</a><ul class='eb-toc__list'><li><a href="#eb-table-content-2">Exemplo básico: criação de um Stream Buffer</a><li><a href="#exemplo-de-escrita-em-uma-tarefa-produtora">Exemplo de escrita em uma tarefa produtora</a><li><a href="#exemplo-de-leitura-em-uma-tarefa-consumidora">Exemplo de leitura em uma tarefa consumidora</a></li></ul><li><a href="#queues-no-freertos-modelo-de-dados-garantias-e-custos-ocultos">Queues no FreeRTOS: modelo de dados, garantias e custos ocultos</a><ul class='eb-toc__list'><li><a href="#eb-table-content-6">Exemplo básico: criação de uma Queue</a><li><a href="#envio-de-dados-para-a-queue">Envio de dados para a Queue</a><li><a href="#eb-table-content-8">Recepção de dados da Queue</a><li><a href="#custos-ocultos-das-queues">Custos ocultos das Queues</a></li></ul><li><a href="#eb-table-content-10">Stream Buffers vs Queues: comparação técnica detalhada e critérios de escolha</a><ul class='eb-toc__list'><li><a href="#eb-table-content-11">Comparação estrutural</a><li><a href="#eb-table-content-12">Critério 1: natureza do dado</a><li><a href="#eb-table-content-13">Critério 2: desempenho e latência</a><li><a href="#eb-table-content-14">Critério 3: topologia produtor–consumidor</a><li><a href="#exemplo-comparativo-uart-rx">Exemplo comparativo: UART RX</a></li></ul><li><a href="#eb-table-content-16">Padrões de uso, boas práticas e armadilhas comuns com Stream Buffers</a><ul class='eb-toc__list'><li><a href="#eb-table-content-17">Boa prática 1: dimensionamento correto do buffer</a><li><a href="#eb-table-content-18">Boa prática 2: uso consciente do trigger level</a><li><a href="#eb-table-content-19">Boa prática 3: sempre respeitar o modelo 1→1</a><li><a href="#armadilha-1-tratar-stream-buffer-como-message-queue">Armadilha 1: tratar Stream Buffer como Message Queue</a><li><a href="#eb-table-content-21">Armadilha 2: ignorar retornos das funções</a><li><a href="#armadilha-3-usar-delays-em-vez-de-bloqueio">Armadilha 3: usar delays em vez de bloqueio</a></li></ul><li><a href="#eb-table-content-23">Conclusão técnica e diretrizes finais de projeto</a></ul></div></div></div></div></div>


<h3 class="wp-block-heading"><strong>Introdução: comunicação entre tarefas no FreeRTOS</strong></h3>



<p>Em sistemas embarcados baseados em <em>Real-Time Operating Systems</em> (RTOS), a comunicação entre tarefas (<em>tasks</em>) e entre interrupções (<em>ISRs – Interrupt Service Routines</em>) é um dos pilares da arquitetura de software. No FreeRTOS, essa comunicação pode ocorrer por diversos mecanismos: <em>queues</em>, <em>semaphores</em>, <em>event groups</em>, <em>task notifications</em> e, mais recentemente, <em>stream buffers</em> e <em>message buffers</em>. Cada um desses mecanismos foi projetado para atender a padrões específicos de troca de dados, com impactos diretos em desempenho, uso de memória, latência e complexidade do código.</p>



<p>Historicamente, as <em>queues</em> foram o principal mecanismo para troca de dados entre tarefas no FreeRTOS. Elas oferecem uma semântica clara, segura e genérica, permitindo o envio de estruturas de dados completas entre produtores e consumidores. No entanto, conforme sistemas embarcados passaram a lidar com <strong>fluxos contínuos de dados</strong> — como áudio, streams de sensores, bytes vindos de UART, SPI, USB ou stacks de rede —, tornou-se evidente que o modelo tradicional de <em>queue</em> não era o mais eficiente para esse tipo de cenário.</p>



<p>É nesse contexto que surgem os <strong>Stream Buffers</strong>, introduzidos para lidar com <strong>dados orientados a fluxo</strong>, onde o mais importante não é a fronteira entre mensagens, mas sim a sequência contínua de bytes. Diferentemente das <em>queues</em>, que operam com itens discretos e de tamanho fixo, os <em>stream buffers</em> operam como um <strong>buffer circular de bytes</strong>, permitindo escrita e leitura parcial, com controle fino sobre bloqueio, timeout e sincronização entre tarefas e ISRs.</p>



<p>Nesta série de artigos sobre FreeRTOS, esta seção tem como objetivo introduzir formalmente o conceito de <em>stream buffers</em>, posicioná-los corretamente dentro do ecossistema de mecanismos de comunicação do sistema operacional e preparar o terreno para uma comparação técnica aprofundada com <em>queues</em>. Ao longo das próximas seções, veremos <strong>como funcionam internamente</strong>, <strong>quando usá-los</strong>, <strong>quando evitá-los</strong> e <strong>como escrever código eficiente e seguro</strong> usando esse recurso.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/">FreeRTOS: Stream Buffers, comparação com Queues e critérios de escolha</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://mcu.tec.br/rtos/freertos-stream-buffers-comparacao-com-queues-e-criterios-de-escolha/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1050</post-id>	</item>
	</channel>
</rss>
