Em sistemas embarcados profissionais, o software precisa ser projetado para que seja previsível, testável, fácil de manter e preparado para evoluir junto com o produto.
Aqui na SDB, adotamos uma arquitetura embarcada em camadas, com separação clara entre drivers de hardware, núcleo de domínio, serviços de aplicação e interface de usuário. Essa organização segue boas práticas de engenharia de software para embarcados e é a base que utilizamos hoje em nossos equipamentos industriais.
Ao longo deste artigo, mostraremos de forma prática como essa organização em camadas facilita o reuso entre produtos diferentes e torna viável incorporar testes automatizados ao ciclo de desenvolvimento, reduzindo a dependência de testes manuais em bancada.
Por que unificamos a arquitetura do nosso software embarcado
Em muitos projetos de embarcados, cada equipamento acaba nascendo com seu próprio código, criado para aquele contexto específico. Mas, com o tempo, aparecem os efeitos colaterais: manter e corrigir problemas em múltiplas bases de código fica cada vez mais difícil, a mesma regra de cálculo precisa ser reimplementada em projetos diferentes, surgem diferenças de comportamento entre produtos que deveriam seguir as mesmas normas e o custo para criar variantes aumenta a cada novo desenvolvimento.
Levando tudo isso em consideração, nossa resposta é optar por adotar uma arquitetura em camadas, pensada para ser reutilizada em diferentes equipamentos e versões de produto, reaproveitando ao máximo o núcleo de lógica e regras do sistema.
Princípios da nossa arquitetura embarcada
A arquitetura que adotamos é inspirada em boas práticas consolidadas de embarcados e foi pensada para atender diferentes tipos de equipamentos industriais. Ela se apoia em alguns princípios fundamentais:
- Separação de responsabilidades: hardware, lógica de domínio, orquestração e interface têm papéis bem definidos.
- Independência de hardware: trocar eletrônica, sensores ou atuadores não deve exigir reescrever regras de negócio.
- Reuso entre produtos: diferentes modelos e variações de equipamento compartilham o mesmo núcleo de domínio.
- Testabilidade desde o início: a arquitetura já nasce preparada para testes automatizados, inclusive com simulação realista de hardware.
Com isso, deixamos de ter um código distinto para cada máquina e passamos a trabalhar sobre uma base comum, que evolui de forma consistente entre produtos.
As camadas da arquitetura
De forma simplificada, organizamos o software embarcado em quatro camadas, sendo:
- Drivers** / HAL**
Na base estão os drivers e a camada de abstração de hardware, que encapsulam cada dispositivo físico (sensores, atuadores, interfaces de comunicação) atrás de interfaces bem definidas. É aqui que concentramos as diferenças entre placas, eletrônicas e periféricos, sem expor esses detalhes para o restante do sistema.
2. Núcleo de domínio
Acima dos drivers fica o núcleo de domínio, onde vivem as regras de negócio e os cálculos específicos da aplicação. Essa camada não conhece detalhes de hardware: ela apenas consome medidas, parâmetros de configuração e produz estados e resultados consistentes.
3. Serviços de aplicação
Na camada de aplicação estão os serviços que orquestram o comportamento do equipamento: ciclo de operação, estados, integração com calibração, armazenamento de dados e geração de relatórios. Eles conectam o núcleo de domínio ao mundo externo de forma controlada.
4. Interface homem–máquina e integração
Por fim, a camada de interface apresenta as informações ao usuário e conversa com outros sistemas (por exemplo, exportação de dados ou sistemas de gestão). Como ela está desacoplada do domínio, podemos evoluir telas, tecnologias de UI e integrações sem impactar a lógica central do equipamento.
Testes automatizados como parte da arquitetura
Essa separação em camadas foi pensada desde o início para suportar testes automatizados. Com o domínio desacoplado do hardware real, conseguimos simular sensores e atuadores por meio de drivers de teste e exercitar o comportamento esperado do equipamento usando apenas software, sem depender de um setup físico a cada alteração.
Isso permite validar algoritmos, regras de negócio e respostas do sistema a diferentes condições de hardware, além de rodar testes de regressão sempre que o código evolui. Na prática, o sistema cresce com muito menos risco de regressões silenciosas, e a capacidade de teste passa a ser um requisito de arquitetura, não um extra opcional.
Benefícios para clientes e para o negócio
Adotar uma arquitetura embarcada em camadas traz benefícios diretos para quem usa os equipamentos: o comportamento fica mais consistente entre diferentes modelos, as atualizações de software chegam de forma padronizada e previsível, e a experiência de uso tende a ser mais coerente, com telas, mensagens e resultados alinhados entre si.
Para a empresa, o ganho está em ter uma base única de código e conhecimento, mais simples de manter e de ensinar para novas pessoas, além de reduzir o custo e o prazo para criar variações de produto. Fica mais fácil responder a novas exigências técnicas ou regulatórias, porque as mudanças são concentradas em pontos bem definidos da arquitetura.
O que buscamos é exatamente isso, uma arquitetura bem estruturada, em camadas claras, com foco em testabilidade e reuso, que permita ao software crescer sem se tornar frágil. Quando as camadas estão bem definidas, e os testes fazem parte do dia a dia, o desenvolvimento embarcado passa a funcionar como um processo de engenharia de fato: previsível, evolutivo e sustentável no longo prazo.
—
Artigo Técnico escrito por: Vinícius Pedrosa
Engenheiro de Sistemas Embarcados
Fontes que influenciaram essas decisões de arquitetura
- Elecia White – Making Embedded Systems: Design Patterns for Great Software
- James W. Grenning – Test-Driven Development for Embedded C