Normalmente programa PICs em C, geralmente para conversores de modo comutado. Ouvi falar de várias ferramentas e padrões de análise estática, como o MISRA C, que podem ser usados para ajudar a melhorar a confiabilidade do código. Eu gostaria de saber mais Quais padrões ou ferramentas podem ser apropriados para o meu contexto?
9
Respostas:
A validação de código incorporado é complicada, especialmente quando se lida com partes de recursos limitados, como PICs. Geralmente, você não tem o luxo de codificar nos casos de teste devido às restrições de memórias da peça e à programação geralmente "em tempo real" realizada nesses tipos de dispositivos.
Aqui estão algumas das minhas diretrizes:
Escreva uma especificação se não houver uma: se você não está codificando com uma especificação, documente o que seu código deve ser, quais são as entradas válidas, quais são as saídas esperadas, quanto tempo deve demorar cada rotina, o que pode e não pode ser obtido derrotado, etc. - uma teoria da operação, fluxogramas, qualquer coisa é melhor que nada.
Comente seu código: Só porque algo é óbvio para você não significa que é óbvio (ou correto) para outra pessoa. Comentários em linguagem simples são necessários para a revisão e a manutenção do código.
Código defensivo: não inclua apenas código para entradas normais. Manipule entradas ausentes, entradas que estão fora do intervalo, estouros matemáticos etc. - quanto mais cantos você cobrir pelo design do código, menos graus de liberdade o código terá quando implantado.
Use ferramentas de análise estática: pode ser humilhante quantas ferramentas de bugs, como o PC-lint, podem encontrar no seu código. Considere uma análise estática limpa como um bom ponto de partida para testes sérios.
As revisões por pares são essenciais: seu código deve estar limpo e bem documentado o suficiente para que possa ser revisado com eficiência por uma parte independente. Verifique seu ego na porta e considere seriamente qualquer crítica ou sugestão feita.
O teste é essencial: você deve fazer sua própria validação e ter uma validação independente do código. Outros podem quebrar seu código de maneiras que você não pode imaginar. Teste todas as condições válidas e todas as condições inválidas que você puder imaginar. Use PRNGs e alimente os dados do lixo. Faça o possível para quebrar as coisas, repare e tente novamente. Se você tiver sorte, poderá executar seu código no modo de depuração e espiar registros e variáveis - caso contrário, precisará ser esperto e alternar LEDs / sinais digitais para ter uma idéia do estado de seu dispositivo. Faça o que for necessário para obter o feedback necessário.
Olhe por baixo do capô: não tenha medo de olhar para o código de máquina gerado pelo seu compilador C. Você pode (vai?) Encontrar lugares onde seu belo código C explodiu em dezenas, senão centenas de operações, onde algo que deveria ser seguro (já que é apenas uma linha de código, certo?) Leva tanto tempo para executar que várias interrupções demitiram e invalidaram as condições. Se algo se tornar terrivelmente ineficiente, refatore-o e tente novamente.
fonte
A maioria das mesmas técnicas para criar software confiável em um PC também é aplicável ao desenvolvimento incorporado. É útil separar seus algoritmos do código específico de hardware e testá-los separadamente com testes de unidade, simulações, análise estática e ferramentas como Valgrind. Dessa forma, há muito menos código que só é testado no hardware.
Eu não abandonaria o C. Embora idiomas como o Ada possam oferecer algumas garantias menores, é fácil cair na armadilha de pensar que o idioma promete mais do que realmente.
fonte
O MISRA-C é realmente muito útil para melhorar a qualidade geral do código e minimizar os erros. Apenas certifique-se de ler e entender todas as regras, a maioria delas é boa, mas algumas não fazem nenhum sentido.
Um aviso aqui. O documento MISRA assume que o leitor é alguém com amplo conhecimento da linguagem C. Se você não possui um veterano C endurecido em sua equipe, mas decide adquirir um analisador estático e seguir cegamente todos os avisos dados, provavelmente resultará em menor qualidade código de , pois você pode reduzir a legibilidade e introduzir bugs por acidente. Eu já vi isso acontecer muitas vezes, a conversão de código para conformidade com MISRA não é tarefa trivial.
Existem duas versões do documento MISRA-C que podem ser aplicadas. Ou MISRA-C: 2004, que ainda é o atual padrão de fato da indústria embarcada. Ou o novo MISRA-C: 2012, que suporta o padrão C99. Se você nunca usou o MISRA-C antes, eu recomendaria que você o implementasse.
No entanto, esteja ciente de que os fornecedores de ferramentas geralmente se referem ao MISRA-C: 2004 quando afirmam que estão verificando o MISRA (às vezes até se referem à obsoleta versão do MISRA-C: 1998). Até onde eu sei, o suporte da ferramenta para MISRA-C: 2012 ainda é limitado. Acho que apenas alguns analisadores estáticos o implementaram até agora: Klocwork, LDRA, PRQA e Polyspace. Pode ser mais, mas você definitivamente precisa verificar qual versão do MISRA ele suporta.
Antes de decidir, é claro que você pode começar lendo o documento MISRA e ver o que ele implica. Ele pode ser comprado por 10 libras na misra.org , bastante acessível comparado aos preços dos padrões ISO.
fonte
O Mathworks (o pessoal do MATLAB) possui uma ferramenta de análise de código estática chamada Polyspace .
Assim como a análise de código estático, fiapos e similares, eu sugeriria definição cuidadosa e design de interfaces (com um processo formal de revisão) e análise de cobertura de código.
Você também pode consultar as diretrizes para o design de códigos críticos para a segurança, incluindo MISRA, mas também os padrões UL1998 e IEC 61508.
fonte
Para uma resposta completa a essa pergunta, eu suprimiria o pensamento sobre "confiabilidade do código" e, em vez disso, pensaria em "confiabilidade do design", porque o código é apenas a expressão final do design.
Portanto, comece com os requisitos e escreva e inspecione-os. Se você não possui um documento de requisitos, aponte para uma linha aleatória de código e pergunte-se "por que essa linha é necessária?" A necessidade de qualquer linha de código deve, eventualmente, ser rastreável a um requisito, mesmo que seja tão simples / óbvio quanto "a fonte de alimentação produzirá 5VDC se a entrada estiver entre 12 e 36VDC". Uma maneira de pensar sobre isso é que, se essa linha de código não pode ser rastreada para um requisito, como você sabe que é o código certo ou que é necessário?
Em seguida, verifique seu design. Tudo bem se estiver completamente no código (por exemplo, nos comentários), mas isso torna mais difícil saber se o código está fazendo o que realmente significa. Por exemplo, o código pode ter uma linha que lê
output = 3 * setpoint / (4 - (current * 5));
Écurrent == 4/5
uma entrada válida que pode causar uma falha? O que deve ser feito neste caso para evitar a divisão por zero? Você evita a operação completamente ou diminui a saída? Ter uma observação geral em seu documento de design sobre como lidar com casos extremos torna muito mais fácil verificar o design em um nível superior. Portanto, agora a inspeção de código é mais fácil porque é uma questão de verificar se o código implementa corretamente esse design.Junto com isso, a inspeção de código deve verificar se há erros comuns que seu IDE não captura (você está usando um IDE, certo?) Como '=' quando você quis dizer '==', faltando chaves que mudam o significado de 'if ', ponto e vírgula onde não deveriam estar, etc.
Enquanto escrevo isso, me ocorre que é realmente difícil resumir anos de treinamento / experiência em qualidade de software em um único post. Escrevo código para dispositivos médicos e o exposto acima é um resumo extremamente simplificado de como o abordamos.
fonte