Software de aplicativo tem uma relação confortável com erros. Algo quebra, uma correção é escrita, e ela é lançada naquela mesma tarde.
Um conjunto diferente de regras
Software embarcado vive dentro de um produto. Um controlador de motor, uma bomba de infusão médica, um veículo, um termostato, um satélite, um sensor de fábrica. As regras mudam de quatro maneiras, e cada uma delas molda como o trabalho é feito.
O hardware é fixo. Se o processador é lento demais, a memória pequena demais ou o periférico errado, não dá para fazer upgrade daquela unidade. Só dá para mudar o software, e eventualmente nem isso.
Os recursos são limitados e pequenos. Quilobytes, não gigabytes, em muitos produtos. A alocação dinâmica de memória costuma ser proibida diretamente, porque uma falha de alocação não tem resposta aceitável, e a fragmentação ao longo de anos de operação contínua é imprevisível.
Os prazos são reais. Perder um pode significar que um motor recebeu um comando errado, que uma malha de controle ficou instável, ou que uma função de segurança não disparou.
A falha é física. Software de aplicativo que falha mostra uma mensagem. Software embarcado que falha move algo, esquenta algo ou para algo.
A disciplina não é definida pela linguagem. É definida por não poder mudar de ideia depois.
O que a trilha abrange
O escopo: microcontroladores, desenvolvimento de firmware, sistemas operacionais de tempo real, interfaces de hardware e software, drivers de dispositivo e segurança embarcada.
Quatro áreas.
Interface com hardware. Registradores, periféricos, interrupções, barramentos de comunicação e a leitura de datasheet que vem junto.
Arquitetura de firmware. Loops bare metal, sistemas operacionais de tempo real, decomposição de tarefas e as decisões de escalonamento por baixo disso.
Programação restrita. Trabalhar dentro de orçamentos de memória, temporização e potência, e provar que você o fez.
Ciclo de vida. Mecanismos de atualização, segurança, diagnóstico e manutenção de longo prazo.
Tempo real significa prazos, não velocidade
O termo é lido errado o tempo todo. Tempo real não é uma afirmação sobre desempenho. É uma afirmação sobre previsibilidade.
Um sistema de tempo real rígido precisa completar uma ação dada antes de um prazo dado, sempre. Desempenho médio é irrelevante. Um sistema que responde em cinquenta microssegundos na média e em cinco milissegundos uma vez por hora não foi rápido na maior parte do tempo. Ele falhou, uma vez por hora.
Três conceitos decorrem disso, e são o núcleo da disciplina.
Tempo de execução no pior caso. Não o típico, não o medido ao longo de uma execução normal. O tempo mais longo que o código pode levar, com todo desvio tomado da pior forma, todo cache perdido e toda interrupção chegando no pior momento. O projeto é feito contra esse número.
Latência de interrupção e jitter. Quanto tempo até o sistema responder a um evento externo, e o quanto isso varia. O jitter importa tanto quanto a latência em aplicações de controle, porque uma malha de controle presume um intervalo de amostragem fixo e degrada quando não o recebe.
Prioridade e escalonamento. O que roda quando várias coisas estão prontas, e o que acontece quando uma tarefa de baixa prioridade segura um recurso que uma tarefa de alta prioridade precisa. Essa situação, inversão de prioridade, já causou falhas reais e bem documentadas em sistemas entregues, e os mecanismos que a previnem existem exatamente porque ela não é óbvia.
Os bugs que só existem em trabalho embarcado
Uma categoria de falha que desenvolvedores de aplicativo raramente encontram e engenheiros embarcados encontram o tempo todo.
Condições de corrida com interrupções. O código principal e uma rotina de interrupção mexendo na mesma variável, com a interrupção caindo entre a leitura e a escrita. Aparece uma vez a cada dez mil execuções e desaparece quando você adiciona um print.
Estouro de pilha. Sem proteção de memória em muitos sistemas pequenos, então a pilha cresce silenciosamente sobre outros dados, e o sintoma aparece em algo não relacionado, bem mais tarde.
Corrupção de memória. Um erro de ponteiro ou estouro de buffer que danifica dados de um subsistema totalmente diferente, produzindo uma falha cuja localização não tem nada a ver com sua causa.
Comportamento dependente de temporização. Código que funciona em uma velocidade de clock, um nível de otimização do compilador ou uma temperatura, e falha em outro.
Heisenbugs. Falhas que somem sob o depurador, porque conectá-lo muda a temporização que as causou.
A consequência prática é que a depuração embarcada depende de ferramentas que observam sem perturbar: trace de hardware, analisadores lógicos, osciloscópios e instrumentação projetada para dentro do produto. Aprender a ler um sinal no osciloscópio não é nostalgia. Muitas vezes é a única forma de ver a falha.
Onde isso se encaixa no domínio
Sistemas embarcados e hardware de computador é a quinta de nove trilhas do domínio de semicondutores, eletrônica e quântica da Astra Trainer. Ela combina com engenharia eletrônica, já que quase toda placa carrega firmware e as duas funções compartilham uma fronteira por onde discutem constantemente, e com projeto de chips, onde programas de system-on-chip precisam das duas equipes fluentes.
Ela também se conecta com robótica, onde a camada de controle é embarcada, com manufatura avançada para controle industrial, e com medicina e healthtech, onde dispositivos carregam obrigações regulatórias. Veja as nove trilhas aqui.
Lançar o produto é o início de uma obrigação de dez anos
Um sensor industrial, um dispositivo médico, um veículo ou um equipamento de infraestrutura predial vai estar em serviço por uma década ou mais. Se ele se conecta a uma rede, esse período inteiro é uma exposição.
Três problemas que separam segurança embarcada de segurança de servidor, e nenhum deles tem resposta simples.
Atualizar é difícil e arriscado. Dispositivos podem estar inacessíveis, funcionar a bateria, ter largura de banda limitada ou estar fisicamente inacessíveis. Uma atualização que falha no meio do caminho pode deixar um dispositivo inutilizável, o que para alguns produtos significa uma visita técnica e, para outros, uma perda total. Atualização segura, retomável e verificada é um problema de projeto que precisa ser resolvido antes que a primeira unidade seja enviada, porque não pode ser adicionado depois a dispositivos já em campo.
A criptografia precisa durar. Chaves e algoritmos escolhidos hoje permanecem nos dispositivos por toda a vida útil deles. É aqui que essa trilha encontra comunicação, sensoriamento e segurança quântica, e a resposta é agilidade criptográfica: projetar para que o algoritmo possa ser substituído, em vez de presumir que a primeira escolha é permanente.
A obrigação é cada vez mais legal. Várias jurisdições introduziram exigências cobrindo produtos conectados, incluindo proibição de senhas padrão universais, divulgação de por quanto tempo atualizações de segurança serão fornecidas, e processos de notificação de vulnerabilidade. Os detalhes variam por mercado e mudam, mas a direção é consistente: suporte de segurança está virando um compromisso declarado com uma duração associada, em vez de uma questão de boa vontade.
As funções, nomeadas
Engenheiros de software embarcado. A função ampla.
Engenheiros de firmware. Mais perto do hardware.
Desenvolvedores de drivers de dispositivo.
Engenheiros de sistemas de tempo real, para aplicações críticas em temporização e controle.
Engenheiros de Linux embarcado, uma especialização distinta do trabalho com microcontroladores.
Engenheiros de integração de hardware e software, fazendo o bring-up de novas placas.
Engenheiros de segurança embarcada. Boot seguro, gestão de chaves, infraestrutura de atualização.
Engenheiros de segurança funcional, para sistemas automotivos, industriais e médicos.
Engenheiros de teste e validação embarcada, incluindo hardware-in-the-loop.
Quem pode ser capacitado para isso
Engenheiros de software de aplicativo. O maior grupo. Trazem estrutura, disciplina de ferramentas e hábitos de controle de versão que equipes embarcadas costumam não ter. O que precisa ser ensinado deliberadamente é o modelo de hardware: registradores, interrupções, temporização, e por que a alocação dinâmica é tratada com suspeita.
Técnicos e engenheiros de eletrônica. Conversão pelo outro lado, já com a intuição de hardware e precisando da estrutura de software.
Pessoal de controle e automação industrial. Programadores de controladores lógicos programáveis já entendem comportamento de tempo real, varredura determinística e restrições industriais.
Engenheiros de teste. Para validação e teste hardware-in-the-loop.
Engenheiros de tecnologia da informação e de rede. Para trabalho com dispositivos conectados e segurança embarcada, onde o conhecimento de protocolo se transfere e as restrições de recurso não.
Engenheiros de campo. Para diagnóstico e engenharia de suporte, segurando o conhecimento de falhas em campo que ninguém no desenvolvimento tem.
Segurança funcional e dispositivos regulados. Software embarcado em dispositivos médicos, veículos, aviação, maquinário industrial e sistemas instrumentados de segurança é regido por normas vinculantes e regimes regulatórios com exigências de processo de desenvolvimento, documentação, verificação e controle de mudanças. Níveis de integridade de segurança são atribuídos por avaliação formal, e a certificação é concedida por organismos competentes. O treinamento constrói capacidade de engenharia e consciência de onde essas obrigações se aplicam. Não concede certificação, status de avaliador de segurança, ou autoridade para liberar software em um produto regulado.
O que levar daqui
Trabalho embarcado é definido por restrições, não por uma linguagem. Hardware fixo, memória pequena, prazos rígidos e uma vida longa.
Tempo real significa cumprir um prazo sempre. Tempo de execução no pior caso é o número que importa, não a média.
Os bugs característicos são falhas de temporização, concorrência e memória que se escondem de depuradores, e é por isso que ferramentas de observação de hardware continuam centrais.
Atualização e agilidade criptográfica precisam ser projetadas antes de a primeira unidade ser enviada, porque não podem ser adicionadas depois a dispositivos já em campo.
E as duas melhores fontes de novos engenheiros embarcados vêm de direções opostas: desenvolvedores de aplicativo que precisam do modelo de hardware, e técnicos que precisam da estrutura de software.
O que tempo real realmente significa?
Cumprir um prazo específico sempre, não rodar rápido. Um sistema que responde depressa na média e ocasionalmente atrasa falhou, porque em aplicações de controle e segurança a resposta atrasada é a que importa.
Por que a alocação dinâmica de memória é evitada em sistemas embarcados?
Porque a alocação pode falhar e frequentemente não há resposta aceitável para essa falha, e porque a fragmentação ao longo de anos de operação contínua é difícil de prever. Muitos projetos alocam de forma estática na inicialização.
Por que bugs embarcados são tão difíceis de reproduzir?
Porque muitos deles dependem de temporização. Corridas de interrupção, estouros de pilha e corrupção de memória produzem sintomas longe de sua causa, e conectar um depurador muda a temporização que os criou.
Por que a segurança embarcada precisa ser projetada com antecedência?
Porque um dispositivo pode ficar em serviço por uma década, e o mecanismo de atualização, a gestão de chaves e a capacidade de trocar algoritmos criptográficos não podem ser adicionados a unidades já implantadas em campo.
Desenvolvedores de aplicativo podem migrar para trabalho embarcado?
Sim, e trazem estrutura e disciplina de ferramentas úteis. A lacuna que precisa ser ensinada explicitamente é o modelo de hardware: registradores, interrupções, comportamento de temporização e restrições de recurso.
