Começando com DevOps para Sistemas Embarcados usando o ATmega328P

Ari Mahpour
|  Criada: Maio 29, 2024  |  Atualizada: Julho 1, 2024
Começando com DevOps para Sistemas Embarcados usando o ATmega328P

DevOps e metodologias Ágeis transformaram o desenvolvimento de software enfatizando a colaboração, automação e melhoria contínua. Aplicar os princípios de DevOps aos meus designs e projetos foi um divisor de águas, aumentando a eficiência e a confiabilidade. Neste artigo, vamos passar pelo processo de configuração de um fluxo de integração contínua (CI) para um projeto de sistemas embarcados existente que utiliza o microcontrolador ATmega328P. Ao final deste artigo, você verá como essas práticas podem otimizar seu processo de desenvolvimento e entregar produtos de maior qualidade.

Entendendo DevOps e Ágil para Sistemas Embarcados

DevOps é um conjunto de práticas, popularizado pelo mundo do software, que une o desenvolvimento de software (Dev) e as operações de TI (Ops) em um fluxo contínuo. No mundo do software, era comum desenvolver o software e “jogá-lo por cima do muro” para os profissionais de operações para implantação nos clientes. DevOps introduziu uma maneira de não apenas derrubar esse muro, mas automatizar todo o processo de ponta a ponta. No mundo do hardware, encontramos semelhanças entre o desenvolvimento de produtos e a produção, constantemente jogando o design “por cima do muro” para nossas equipes de engenharia de manufatura para garantir que tudo esteja pronto para a produção.

No design de produtos embarcados ainda temos que passar nosso software pela produção, mas enfrentamos o desafio de nos mover mais rápido do que nunca e entregar na mais alta qualidade possível. Com os princípios de DevOps, visamos resolver alguns desses desafios.

  • Dependências de Hardware: Sistemas embarcados dependem de hardware e revisões específicas dessas PCBs. Isso pode tornar os testes e a implantação complexos se não forem simplificados para serem automatizados e altamente escaláveis. As práticas de DevOps ajudam a automatizar esses processos usando a mesma configuração para o hardware e o software e colocando-os em sistemas de integração contínua (CI) automatizados.
  • Tempos de Construção Longos: Construir software embarcado pode ser difícil de configurar e resultar em tempos de construção longos. CI automatiza e acelera esse processo ao transferir as construções para a nuvem utilizando instâncias mais robustas que os desenvolvedores normalmente não têm acesso.
  • Testes Manuais: Testar em hardware real é essencial, mas muitas vezes manual, tedioso e demorado. A automação por meio de testes hardware-in-the-loop (HIL) melhora a eficiência e a precisão e pode ser transferida para um conjunto de equipamentos de teste automatizados configurados com seu sistema CI.

Aplicando os princípios de DevOps, somos capazes de iterar rapidamente usando metodologias Ágeis dentro do paradigma construir-testar-implantar para cada recurso adicional que desejamos lançar para produção.

Como Tudo Funciona

“Construir, testar e implementar” é um conjunto comum de palavras que você frequentemente ouvirá ao discutir DevOps. Em sistemas embarcados fazemos a mesma coisa, pois nossa implementação também vai para produção (e então para o cliente final). No repositório do projeto estamos usando Gitlab CI para conduzir nosso fluxo de trabalho de ponta a ponta para DevOps Embarcado. Usamos o que é chamado de “pipelines” para criar tarefas que alcançam certas atividades como compilar o software, executar testes no alvo, ou liberá-lo como um pacote oficial. No Gitlab, um pipeline é uma coleção de tarefas que são executadas em uma sequência como esta:

Exemplo de pipeline

Figura 1: Exemplo de pipeline usado com o fluxo de trabalho DevOps ATmega328P no Gitlab

Aqui está uma decomposição do script CI (.gitlab-ci.yml) para dar uma ideia de como isso funciona.

  • Docker: Como discutido em Containerizando Ambientes de Construção e Execução para Testes de Hardware em Loop, esta etapa constrói imagens Docker para criar um ambiente consistente para construir, testar e gravar o código. Isso garante que o processo de construção seja reproduzível em diferentes máquinas e arquiteturas (como um PC desktop versus um Raspberry Pi).
  • Teste: Esta etapa executa testes unitários para verificar se o seu código está fazendo o que você pretende que ele faça. Testes automatizados são rápidos e importantes ao modificar ou refatorar código existente.
  • Construir: Esta etapa compila o código-fonte em binários. Neste projeto, gera artefatos como arquivos .elf e .hex, que são usados para gravar o chip ATmega328P.
  • HIL (Hardware-in-the-Loop): Esta etapa envolve testar o software em hardware real para garantir que funciona corretamente em condições do mundo real. Carrega o software no hardware e executa testes para verificar a funcionalidade que projetamos realmente funciona no produto final.
  • Implementar: Esta etapa lida com a publicação dos artefatos construídos em um registro de pacotes, tornando-os disponíveis para uso.
  • Lançamento: Esta etapa cria um novo lançamento de software, automatizando o processo de entrega para garantir atualizações rápidas e confiáveis. Isso é o que a equipe de produção usaria para recuperar a versão do software necessária para toda a montagem do produto.

Detalhes Finos

Há alguns detalhes menores que levam esse fluxo de trabalho de uma implementação básica de DevOps para um sistema que funciona de maneira suave, bem documentada e facilmente observável. Há alguns detalhes sutis dentro do fluxo de trabalho CI que são importantes de apontar.

  • Versionamento Semântico: Definir uma versão, seja por um mecanismo automatizado ou manualmente, é extremamente importante para o ciclo de lançamento, especialmente ao trabalhar com produção. Como exemplo, isso é definido como uma variável dentro do script CI e depois usado nos trabalhos de publicação e lançamento.
  • Lógica de construção Docker: Você notará que há um bloco de lógica que é usado para as construções de contêineres Docker:

 


if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then

  export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:latest

else

  export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:$CI_COMMIT_REF_SLUG

fi

 

Esta lógica prepara o cenário para nosso rótulo “latest” usar apenas a imagem Docker construída na branch principal (ou seja, após uma solicitação de merge ser aprovada com sucesso). Isso garante que apenas solicitações de merge bem-sucedidas publiquem a imagem docker mais recente e mais avançada da qual todos e cada pipeline retiram.

  • Relatórios e Cobertura: Em sistemas CI modernos como o Gitlab, podemos extrair e exibir relatórios de teste e cobertura dentro de nossas solicitações de merge e pipelines. Por exemplo, nesta solicitação de merge, capturamos a cobertura de código:
Cobertura de código dentro de uma solicitação de merge

Figura 2: Cobertura de código dentro de uma solicitação de merge

Nesta captura de tela, o Gitlab resume os testes executados no alvo usando hardware in the loop:

Resumo de teste para testes executados no alvo

Figura 3: Resumo de teste para testes executados no alvo

No final, uma vez que nosso código foi validado tanto com testes unitários quanto no alvo, as etapas de publicação e lançamento geram um pacote agradável que pode ser consumido pela equipe de produção:

Lançamento de pacote de software

Figura 4: Lançamento de pacote de software

Com todos esses passos automatizados, podemos lançar uma nova funcionalidade de forma iterativa em um modo Ágil. Não há necessidade de desenvolver muitas funcionalidades, enviá-las para o departamento de QA e, então, uma revisão para lançamento do pacote pela equipe de produção. Tudo aqui acontece em um único fluxo de trabalho e é completamente automatizado.

Conclusão

Neste artigo, exploramos como as metodologias DevOps e Agile podem ser aplicadas ao desenvolvimento de sistemas embarcados, especificamente usando o microcontrolador ATmega328P. Discutimos os benefícios de implementar um fluxo de trabalho CI no Gitlab, que inclui automação, tempos de construção mais rápidos e testes eficientes. Ao detalhar o script CI e explicar cada estágio, mostramos como criar um processo de desenvolvimento robusto e otimizado que aumenta a eficiência e a qualidade do produto. Seguindo este guia prático (e o código-fonte dentro do repositório), você também deverá ser capaz de configurar seu próprio fluxo de trabalho Embedded DevOps.

O código-fonte do projeto pode ser encontrado aqui:https://gitlab.com/embedded-designs/atmega328p-serial-led-control.

Sobre o autor

Sobre o autor

Ari is an engineer with broad experience in designing, manufacturing, testing, and integrating electrical, mechanical, and software systems. He is passionate about bringing design, verification, and test engineers together to work as a cohesive unit.

Recursos relacionados

Documentação técnica relacionada

Retornar a página inicial
Thank you, you are now subscribed to updates.