Intégration de PVS-Studio dans PlatformIO

Image 5

Récemment, dans l'environnement de développement de systèmes embarqués PlatformIO, la prise en charge de PVS-Studio est apparue. Dans cet article, vous apprendrez à tester votre code avec un analyseur statique en utilisant un projet ouvert comme exemple.

Qu'est-ce que PlatformIO?


PlatformIO est un outil de programmation de microcontrôleur multiplateforme. Le cœur de PlatformIO est un outil en ligne de commande, mais il est recommandé de l'utiliser comme plug-in pour Visual Studio Code. Un grand nombre de puces et de cartes mères modernes basées sur celles-ci sont prises en charge. Il est capable de télécharger automatiquement les systèmes d'assemblage appropriés et le site possède une grande collection de bibliothèques pour gérer les composants électroniques enfichables. Il existe un support pour plusieurs analyseurs de code statique, y compris PVS-Studio.

Importer un projet


Pour le démontrer, prenons le programme de contrôle des hexapodes ArduPod sur la carte Arduino Mega.


Créez un nouveau projet pour une carte appropriée et copiez le code source:

Image 2

Dans le dossier / arduino / AP_Utils / examples / il y a plusieurs exemples de programmes pour configurer et exécuter l'hexapode, nous utiliserons servo_test.ino. Le programme pour Arduino, en règle générale, est créé sous forme de croquis au format INO, ce qui dans ce cas n'est pas entièrement adapté. Pour en faire un fichier .cpp correct, il suffit généralement de modifier l'extension du nom de fichier, d'ajouter l'en-tête #include <Arduino.h> au début et de s'assurer que les fonctions et les variables globales sont déclarées avant d'y accéder.

Image 3

Au cours du processus d'assemblage, des erreurs peuvent se produire concernant le manque de bibliothèques tierces requises. Cependant, PlatformIO vous aidera à les trouver dans votre référentiel.

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.

Le lien affichera les options appropriées, et l'installation de la dépendance se fait avec une seule commande dans le terminal:

pio lib install "Adafruit PWM Servo Driver Library"

Configuration des analyseurs et démarrage d'un test


Pour configurer les analyseurs, vous devez éditer la configuration platformio.ini comme ceci:

[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

Le paramètre check_tool indique les analyseurs de code à utiliser et leur configuration est effectuée dans le paramètre check_flags . Des instructions plus détaillées peuvent être trouvées dans la documentation sur le site officiel: https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html

Enfin, vous pouvez exécuter une vérification de projet avec une commande dans le terminal. Avant le premier test, l'environnement lui-même télécharge la distribution actuelle de l'analyseur.

pio check

Le résultat de la vérification du programme hexapode


Cette fois, l'objectif de l'article est de démontrer l'intégration de PVS-Studio avec PlatformIO, et non de démontrer les capacités de diagnostic de l'analyseur. Cependant, une fois le projet vérifié, considérez quelques erreurs trouvées pour montrer que le projet a été analysé avec succès.

V519 Il existe des sous-expressions identiques à gauche et à droite de l'opérateur '-': 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));
    ....
  }
  ....
}

Deux expressions identiques sont soustraites l'une de l'autre. La signification mathématique de cette différence n'est pas claire. Peut-être que le programmeur n'a tout simplement pas réduit l'expression. Ou peut-être une faute de frappe est autorisée, et un autre argument doit être à la place de l'un de ces t .

V550 Une comparaison étrange et précise: valeur! = - 1. Il est probablement préférable d'utiliser une comparaison avec une précision définie: 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;
}

Un avertissement indique une comparaison inexacte des nombres à virgule flottante. En raison de l'impossibilité d'une représentation précise des nombres réels par un nombre fini de bits, il est plus sûr d'établir l'égalité des nombres fractionnaires en comparant leur différence avec un indice de précision donné. Par exemple, quelque chose comme ceci:

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

La seule option sûre pour comparer directement des nombres non entiers consiste à affecter des constantes aux variables, puis à comparer leurs valeurs avec ces constantes. Dans ce cas, la valeur de la variable valeur nulle ne sont pas spécifiquement attribué -1. Voici comment fonctionne la méthode appelée AP_Utils :: sr04 , qui retourne la valeur vérifiée:

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;
  }
}

Comme vous pouvez le voir, la valeur est écrite le résultat de certains calculs. L'affectation -1 est nulle part, mais AP_Utils :: sr04 peut retourner 0, ce qui suggère que la comparaison n'est pas faite avec le résultat.

Conclusion


Dans cet article, nous avons examiné le processus de vérification des projets sur des microcontrôleurs avec un analyseur de code statique dans l'environnement de programmation pour les systèmes PlatformIO intégrés. Permettez-moi de vous rappeler que tous ceux qui veulent essayer PVS-Studio peuvent utiliser le mode d'essai et pour les projets ouverts, il est possible d'obtenir une licence gratuite .

Pour ceux qui veulent en savoir plus sur les fonctionnalités de PVS-Studio plus en détail, je vous conseille de consulter les articles suivants:




Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction: Alexey Govorov. Intégration de PVS-Studio dans PlatformIO .

All Articles