Integração do PVS-Studio no PlatformIO

Quadro 5

Recentemente, no ambiente de desenvolvimento de sistema incorporado PlatformIO, o suporte ao PVS-Studio apareceu. Neste artigo, você aprenderá como testar seu código com um analisador estático usando um projeto aberto como exemplo.

O que é o PlatformIO?


O PlatformIO é uma ferramenta de programação de microcontroladores multiplataforma. O núcleo do PlatformIO é uma ferramenta de linha de comando, mas é recomendável usá-lo como um plug-in para o Visual Studio Code. Um grande número de chips e placas-mãe modernos baseados neles são suportados. É capaz de baixar automaticamente sistemas de montagem adequados, e o site possui uma grande coleção de bibliotecas para gerenciar componentes eletrônicos de plug-in. Há suporte para vários analisadores de código estático, incluindo o PVS-Studio.

Projeto de importação


Para demonstrar, vamos dar o ArduPod hexapod programa de controle sobre o Arduino mega bordo.


Crie um novo projeto para um quadro adequado e copie o código fonte:

Quadro 2

Na pasta / arduino / AP_Utils / examples / existem vários exemplos de programas para configurar e executar o hexapod, usaremos servo_test.ino. O programa para o Arduino, via de regra, é criado na forma de esboços no formato INO, que neste caso não é totalmente adequado. Para criar um arquivo .cpp correto, geralmente é suficiente alterar a extensão do nome do arquivo, adicionar o cabeçalho #include <Arduino.h> ao início e garantir que as funções e variáveis ​​globais sejam declaradas antes de acessá-los.

Quadro 3

Durante o processo de montagem, podem ocorrer erros sobre a falta de bibliotecas de terceiros necessárias. No entanto, o PlatformIO o ajudará a encontrá-los em seu repositório.

In file included from src\servo_test.cpp:20:0:
src/AP_Utils.h:10:37: fatal error: Adafruit_PWMServoDriver.h:
No such file or directory
*******************************************************************************
* Looking for Adafruit_PWMServoDriver.h dependency? Check our library registry!
*
* CLI> platformio lib search "header:Adafruit_PWMServoDriver.h"
* Web> https://platformio.org/lib/search?query=header:Adafruit_PWMServoDriver.h
*
*******************************************************************************
compilation terminated.

O link mostrará as opções apropriadas e a instalação da dependência é feita com um comando no terminal:

pio lib install "Adafruit PWM Servo Driver Library"

Configurando Analisadores e Iniciando um Teste


Para configurar os analisadores, você precisa editar a configuração platformio.ini da seguinte maneira:

[env:megaatmega2560]
platform = atmelavr
board = megaatmega2560
framework = arduino
check_tool = pvs-studio
check_flags =
  pvs-studio:
    --analysis-mode=4 ; General analysis mode. Set to 32 for MISRA
    --exclude-path=/.pio/libdeps ; Ignore dependency libraries

O parâmetro check_tool indica quais analisadores de código usar e sua configuração é feita no parâmetro check_flags . Instruções mais detalhadas podem ser encontradas na documentação no site oficial: https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html

Finalmente, você pode executar uma verificação de projeto com um comando no terminal. Antes do primeiro teste, o próprio ambiente baixa a distribuição atual do analisador.

pio check

O resultado da verificação do programa hexapod


Desta vez, o objetivo do artigo é demonstrar a integração do PVS-Studio com o PlatformIO, e não demonstrar os recursos de diagnóstico do analisador. No entanto, após a verificação do projeto, considere alguns erros encontrados para mostrar que o projeto foi analisado com êxito.

V519 Existem subexpressões idênticas à esquerda e à direita do operador '-': pow (t, 2) - pow (t, 2). AP_Utils.cpp 176

pointLeg* AP_Utils::traceLeg(uint8_t leg, float phi, float z,
  int resolution, uint8_t shape) {
  ....
  if(shape == ELLIPTIC) {
    ....
    float v = sqrt(pow(phi - legs[leg].phi, 2) + pow(z - legs[leg].z, 2));
    float u = sqrt(pow(phi - phi0, 2) + pow(z - z0, 2));
    float t = sqrt(pow(phi0 - legs[leg].phi, 2) + pow(z0 - legs[leg].z, 2));
    theta = acos((pow(t, 2) - pow(t, 2) - pow(v, 2))/(-2.0*t*u));
    ....
  }
  ....
}

Duas expressões idênticas são subtraídas uma da outra. Não está claro qual é o significado matemático dessa diferença. Talvez o programador simplesmente não tenha reduzido a expressão. Ou talvez seja permitido um erro de digitação, e outro argumento deve estar no lugar de um desses t .

V550 Uma comparação estranha e precisa: valor! = - 1. Provavelmente é melhor usar uma comparação com precisão definida: fabs (A - B)> Epsilon. AP_Utils.cpp 574

float AP_Utils::sr04_average(uint8_t trig, uint8_t echo,
  int unit, int samples, int time) {
  ....
  float average, pause, value;
  ....
  for(int i=0; i<samples; i++) {
    value = sr04(trig, echo, unit);
    if(value != -1) { // <=
      total += value;
      delay(pause);
    } else {
      i--;
    }
  }
  average = total/samples;
  ....
  return average;
}

Um aviso indica uma comparação imprecisa dos números de ponto flutuante. Devido à impossibilidade de representação precisa de números reais por um número finito de bits, é mais seguro estabelecer a igualdade de números fracionários comparando sua diferença com um determinado índice de precisão. Por exemplo, algo como isto:

bool is_equal(double x, double y) {
  return std::fabs(x - y) < 0.001f;
}

A única opção segura para comparar diretamente números não inteiros é atribuir constantes às variáveis ​​e comparar seus valores com essas constantes. Neste caso, o valor da variável de valor em qualquer lugar não especificamente atribuído -1. É assim que o método chamado AP_Utils :: sr04 funciona , que retorna o valor verificado:

float AP_Utils::sr04(uint8_t trig, uint8_t echo, int unit) {
  ....
  float duration, distance;
  ....
  duration = pulseIn(echo, HIGH);
  distance = (346.3*duration*0.000001*unit)/2; // <=
  
  if((distance >= 0.02*unit) && (distance <= 4*unit)) {
    ....
    return(distance);
  } else {
    ....
    return 0;
  }
}

Como você pode ver, o valor está escrito como resultado de alguns cálculos. A atribuição -1 não está em lugar algum, mas AP_Utils :: sr04 pode retornar 0 e isso sugere que a comparação não é feita com o resultado.

Conclusão


Neste artigo, examinamos o processo de verificação de projetos em microcontroladores com um analisador de código estático no ambiente de programação para sistemas PlatformIO incorporados. Deixe-me lembrá-lo de que qualquer pessoa que queira experimentar o PVS-Studio pode usar o modo de teste e, para projetos abertos, há uma oportunidade de obter uma licença gratuita .

Para aqueles que desejam aprender mais sobre os recursos do PVS-Studio com mais detalhes, aconselho a procurar os seguintes artigos:




Se você deseja compartilhar este artigo com um público que fala inglês, use o link para a tradução: Alexey Govorov. Integração PVS-Studio no PlatformIO .

All Articles