Quais ferramentas ou padrões podem ser usados ​​para melhorar a confiabilidade do código C incorporado?


9

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?


11
Como você está no idioma C?
Brian Drummond

11
Eu poderia ser persuadido a mudar para outra coisa se houvesse um argumento muito bom a ser feito. Mas teria que ser um caso muito bom.
precisa

Um "argumento muito bom" para mudar de C não pode ser apresentado rapidamente, e para o PIC, possivelmente ainda não. Para AVR, ARM ou MSP430, Ada valeria uma olhada séria (apesar da negatividade que atrai, como você pode ver!) E, para alto rel, SPARK vale uma olhada.
Brian Drummond

Você pode achar isso interessante como informações básicas: SPARK vs MISRA-C spark-2014.org/entries/detail/… e este estudo de caso em andamento: spark-2014.org/uploads/Nosegearpaper_1.pdf
Brian Drummond

Pode ser melhor investir tempo para defender a mudança do PIC para algo moderno ... Especialmente se você estiver projetando o tipo de sistemas de missão crítica para os quais o MISRA e o SPARK foram originalmente projetados.
Lundin 29/01

Respostas:


11

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.


+1 Todos os conselhos de som. Eu esperaria que qualquer desenvolvedor de firmware profissional sorrisse e assentisse ao ler isso.
Lundin 29/01

2
Um aspecto importante das revisões por pares é que a revisão é sobre o código, não sobre o programador. Se você analisar seu código com termos como "primeiro faço isso, depois faço isso", provavelmente você está com problemas. "Primeiro o código faz isso, depois faz aquilo" é o caminho certo para pensar sobre isso. E o mesmo se aplica aos revisores: não "por que você fez isso?", Mas "por que o código faz isso?".
Pete Becker

Você também pode considerar adicionar: 1. Usando a verificação da Complexidade
Ciclomática

4

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.


Valgrid pode ser um pouco mordeu mais relevante para PC do que para um 8-bit MCU, no entanto :)
Lundin

Infelizmente, algumas técnicas para criar um bom software no nível de PC não são adequadas para micros pequenos, e algumas práticas consideradas Ruim e Erradas na área de PCs são perfeitamente aceitáveis ​​em um ambiente incorporado.
John U

3

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.


1

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.


Eu não recomendo ir perto da IEC 61508, a menos que você precise. Ele menciona software, mas carece de fontes científicas modernas para suas reivindicações. Esse padrão chegou 30 anos tarde demais - se tivesse sido lançado nos anos 70 como a maioria de suas chamadas "fontes", poderia ter sido útil.
Lundin

1

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.


Meu entendimento é que a parte do código em um dispositivo médico é testada quase como se fosse um dispositivo separado. Isso é preciso?
21814 Scott Seidman

@ScottSeidman Provavelmente, ele é testado com base nos requisitos, conforme mencionado nesta resposta. Para cada requisito, você deve ter um módulo de código e, para cada módulo de código, deve fazer um teste. Portanto, essencialmente, cada requisito tem um teste correspondente e o código é o meio para atender ao requisito. Esse tipo de rastreamento de requisitos é uma prática comum em qualquer sistema de missão crítica, muito antes do surgimento da palavra-chave "TDD".
Lundin

Eu estava me referindo especificamente às orientações da FDA, como fda.gov/downloads/RegulatoryInformation/Guidances/ucm126955.pdf O software realmente requer mais do que você imagina se fizer parte de um dispositivo médico, começando na etapa de planejamento e nos controles de design.
21813 Scott Seidman

Scott, nunca pensei nisso dessa maneira, mas você está correto. Nosso pessoal de Garantia de Qualidade de Software verifica o software separadamente do resto do sistema (tanto quanto possível) antes de entregá-lo a um grupo diferente responsável pela Verificação e Validação do Sistema.
precisa saber é
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.