sexta-feira, abril 28, 2006

Bugs Terríveis de Achar - Execução Paranormal de Código

Os dois últimos dias foram de uma busca frenética atrás de um bug.

O bug se apresentou em um firmware que estamos desenvolvendo para um dispositivo e que roda em um microcontrolador. A programação deste tipo (sistema embarcado) é bem diferente da programação normal para PC. Como é comum nestes casos, o firmware é gravado em uma memória não volátil (memória Flash) dentro do próprio microcontrolador. Esta gravação é feita por um software de PC, através de um gravador ligado à porta paralela do PC e a determinados pinos do microcontrolador.

Uma segunda memória não volátil (EEProm), externa ao microcontrolador, é usada para manter dados não voláteis, alguns deles extremamente críticos para a operação (como o número de série do dispositivo). A gravação na EEProm requer uma série de passos: é preciso habilitar a gravação, enviar o comando de gravação, o endereço e o dado. Não é algo que possa acontecer por conta própria.

No processo de produção dos dispositivos, é gravado primeiro um software de teste no microcontrolador. Através de uma serial de debug, são feitos testes e gravadas as informações críticas. Após isto é gravado o firmware normal.

Bem, após a produção de 140 dispositivos, verificou-se que cerca de uma dúzia estava com número de série incorreto. Pânico! Uma primeira hipótese, erro de operação na produção, parece improvável dado a taxa de erros. Restam o software de teste estar gravando algo errado ou, pânico maior, o firmware normal estar destruindo as informações na EEProm. Por outro lado, este efeito nunca tinha sido observado com as duas dezenas de protótipos.

Uma primeira revisão do firmware mostra que a EEProm é gravada em poucos pontos. Segue-se uma discussão filosófica sobre a necessidade e conveniência destes pontos. Faz sentido colocar um número de série default em caso erro de checksum na EEProm? A conclusão é que o firmware normal deve evitar ao máximo gravar na região onde estão os parâmetros mais críticos. Entretanto, mudar isto antes de descobrir o que está acontecendo pode apenas mascarar um problema sério.

A decisão é acrescentar um teste para tentar pegar se o número de série está danificado. Se sim, acender um LED de erro e preservar o conteúdo da EEProm para ver se dá uma pista do que ocorre. Em seguida, tentar reproduzir o problema, refazendo o procedimento de produção com esta nova versão.

Feito o procedimento com 20 dispositivos, em 2 ocorre o erro. É uma boa notícia: o problema pode ser reproduzido.

Alguns testes mostram que o software de teste está gravando os valores corretos na EEProm. Hora de ativar os traces do firmware e observar as informações enviadas pela serial. Após alguma tentativas, verifica-se que a corrupção da EEProm ocorre logo após a carga do firmware.

O teste começa a ficar mais complicado. É preciso prestar atenção no trace enviado pelo dispositivo quando ele é re-iniciado após a carga. É um problema esporádico, às vezes ocorre apenas após muitas tentativas. Para dificultar, às vezes ocorre um erro na verificação feita após a gravação. Outras vezes, a execução do firmware não acontece ao final da gravação e verificação, sendo preciso esticar o braço e desligar e re-ligar o dispositivo.

Prestando mais atenção, percebe-se que o firmware executa mesmo quando ocorre um erro na verificação. Em uma destas ocasiões, o conteúdo da EEProm é danificado. Primeira teoria: o firmware executado estava danificado de uma forma que causou a gravação incorreta da EEProm. Segue-se uma discussão de como o firmware pode descobrir que está gravado errado e não executar neste caso (a técnica tradicional é colocar um checkum no código, obviamente não resolve se a rotina de verificação estiver danificada).

Segue-se mais bateria de testes, tentando ver se sempre que a EEProm é danificada ocorreu erro na verificação. Alguns minutos depois, teoria abalada: a EEprom foi corrompida sem que tivesse ocorrido erro de verificação.

Para tentar cercar mais o problema, coloquei na rotina de gravação da EEProm (no mais baixo nível) um teste do endereço de gravação. Se for o endereço do número de série, ao invés de gravar envia um ! para a serial. Mais algumas tentativas e aparece !!! isolado, sem os demais traces...

Olhando com mais atenção ainda, percebemos que existe alguma atividade no dispositivo durante a verificação da gravação, quando o processador devia estar parado. Nova teoria: existe algo errado no processo de gravação e verificação, que faz o processador iniciar a execução antes da hora e de forma "meio torta".

Para comprovar, coloquei uma variável que é iniciada com zero e incrementada a cada passo da iniciação do software. Na rotina de escrita na EEProm, acrescentei um teste: se não tiverem sido executados todos os passos da iniciação, envia pela serial @ seguido do valor do contador. Alguns poucos testes são suficientes para ver alguns @0 e @1 surgirem durante a verificação. Execução paranormal: a rotina de gravação está sendo executada desrespeitando o fluxo normal da execução.

Hora de reclamar do gravador para o projetista do hardware. Aparentemente o processador está recebendo um sinal de reset fora de hora. Após algumas tentativas de achar uma explicação no software para o comportamento anormal, decide-se colocar um capacitorzinho no sinal de reset que vem do gravador (algo como dar um tempinho em software). Antes de soldar o capacitor, o técnico decidiu verificar o cabo. Tinha um mau contato no pino de reset. Testes com um outro cabo e com o cabo com o mau contato eliminado confirmam que o problema sumiu.

Resumindo, um mau contato no cabo usado para gravar o firmware fazia com que ocasionalmente o sinal de reset "balança-se" durante a verificação da gravação. Isto deixava o processador meio "bêbado" e ele saia executando errado o firmware.

Agora é só eliminar todos os problemas potenciais que identificamos enquanto procurávamos o bug que não existia.

4 comentários:

Anônimo disse...

haha.. que hilário.. muito legal

Anônimo disse...

Dividir e conquistar. :-)

O problema é quando isso acontece nas vésperas da entrega de um produto...

Anônimo disse...

Fico feliz em saber que existe desenvolvimento ativo com micro-controladores nos dias atuais. Sou um programador C/C++ para softwares de baixo nível e durante meu curso de Engenharia da Computação me foi despertada a idéia de resolver alguns problemas com PIC. (Pois é, apesar dos 30 anos, estou no meio de um curso universitário, mas este é outro assunto). Tenho a intensão de utilizar micro-controladores em meu projeto de formatura e assim conquistar algum espaço nesta especialidade. Eu tinha para mim mesmo que eu apenas veria este tipo de desenvolvimento durante a faculdade. O Kit da Mosaico foi de excelente introdução e agora estou partindo para algo mais completo, e estou esbarrando no pequeno impecílio de não ter um osciloscópio para ajudar a depurar o um filtro de protocolo serial que pretendo apresentar. Mas um problema de cada vez :-). Este post me deu a esperança de um dia poder trabalhar com isso. Assim como eu pensava que nunca trabalharia com desenvolvimento em Kernel-Mode para windows aqui no Brasil, eu pensava o mesmo para micro-controladores. Este tipo de problema descrito do seu post são ao mesmo tempo terríveis de enfrentar, mas ao mesmo tempo muito gratificante quando o resolvemos. Me diga DQ, posso alimentar esta esperança ou a empresa onde você trabalha é a única no Brasil que faz este tipo de coisa? Vou terminar perguntando se você tem alguma recomendação para mim.

Grande abraço,

Fernando Roberto da Silva
fernando.rsilva(at)gmail.com

Daniel Quadros disse...

Fernando,

Existem sim empresas no Brasil que desenvolvem hardware e software com microcontroladores. Não são empresas com muita visibilidade e normalmente se concentram em nichos bem específicos, mas elas estão aí.