Validation de l'intégrité de la mémoire DDR sur microcontrôleurs

Dans le développement de systèmes embarqués, la stabilité de la mémoire (DDR, SRAM, FLASH, etc.) est un facteur critique. Des défaillances peuvent entraîner des comportements logiciels erratiques, rendant le débogage extrêmement complexe. Une approche préventive consiste à effectuer des tests approfondis de lecture/écriture mémoire. Il est important de noter que ces vérifications constituent un dépistage initial et ne détectent pas toutes les anomalies possibles.

Outil de Test : memtester

Pour évaluer la fiabilité de la mémoire, un outil largement reconnu est memtester. Sa dernière version, la 4.7.1, offre un ensemble complet de tests.

Types de Tests Comportementaux de la Mémoire

memtester intègre diverses routines de test, chacune ciblant des modes de défaillance spécifiques. Voici quelques-uns des principaux types de tests inclus :

Vérification des Lignes d'Adresse (Stuck Address Test)

Ce test fondamental examine la capacité de la mémoire à être adressée correctement. Il écrit des motifs spécifiques à des adresses paires (l'adresse elle-même) et impaires (le complément bit à bit de l'adresse), puis vérifie l'intégrité des données après relecture. Cette opération est répétée plusieurs fois. Un échec à ce stade est un indicateur fort d'un problème matériel sérieux dans le sous-système mémoire, rendant les résultats des tests ultérieurs non fiables.

Tests de Cohérence Basés sur des Opérations Logiques et Arithmétiques

Cette catégorie de tests divise la zone mémoire à évaluer en deux segments égaux. Des opérations (par exemple, valeurs aléatoires, XOR, soustraction, multiplication, division, OR, AND, incrément séquentiel) sont appliquées de manière identique à chaque segment, et les résultats sont ensuite comparés. L'objectif est de détecter des incohérences. Cependant, ces tests ont des limites ; par exemple, une section de mémoire qui retournerait toujours zéro, indépendamment de ce qui est écrit, pourrait passer ces tests.

  • random_value_check (Vérification de valeurs aléatoires)
  • xor_comparison (Comparaison XOR)
  • sub_comparison (Comparaison par soustraction)
  • mul_comparison (Comparaison par multiplication)
  • div_comparison (Comparaison par division)
  • or_comparison (Comparaison OR)
  • and_comparison (Comparaison AND)
  • sequential_increment_comparison (Compariason par incrément séquentiel)

Tests de Modèles pour Détecter les Erreurs de Bit et la Diaphonie

Ces tests écrivent des motifs spécifiques à travers la mémoire, tels que des séquences de bits (tout à zéro, tout à un, 0x55555555, 0xAAAAAAAA) ou des motifs en "damier" (checkerboard), pour révéler des problèmes comme les inversions de bits, la diaphonie entre bits (crosstalk), ou l'instabilité de bits individuels.

  • solid_bits_check (Vérification de bits solides - tout à 0/1)
  • block_sequential_check (Vérification de blocs séquentiels)
  • checkerboard_pattern_check (Vérification du motif en damier)
  • bit_flip_detection (Détection d'inversion de bit)
  • walking_ones_interference (Interférence par bit unique '1' mobile)
  • walking_zeroes_interference (Interférence par bit unique '0' mobile)

Mise en Œuvre des Tests

Les tests peuvent être exécutés à la fois dans un environnement Linux et sur un microcontrôleur bare-metal. Des implémentations adaptées sont disponibles :

Test de Mémoire sous Linux

Étape 1 : Acquisition du Code Source

$ git clone https://github.com/surez-ok/mcu_toolset.git

Étape 2 : Compilation

Pour compiler l'exécutable sur la machine hôte :

$ cd mcu_toolset/memtester/linux
$ make

Vérifiez le type de fichier de l'exécutable :

$ file memtester

Exemple de sortie :

memtester: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

Pour la compilation croisée, par exemple pour une architecture RISCC-V :

$ make clean
$ make CC=riscv64-unknown-linux-gnu-gcc LD=riscv64-unknown-linux-gnu-gcc LDFLAGS=-static

Cette commande utilise la chaîne d'outils de compilation croisée spécifiée et lie statiquement l'exécutable.

Vérifiez à nouveau le type de fichier :

$ file memtester

Exemple de sortie pour RISC-V :

memtester: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, for GNU/Linux 4.15.0, stripped

Étape 3 : Exécution du Test

# ./memtester 64M 3
memtester version 4.7.1 (64-bit)
Copyright (C) 2001-2024 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 64MB (67108864 bytes)
got  64MB (67108864 bytes), trying mlock ...locked.
Loop 1/3:
  Stuck Address       : ok
  Random Value        : ok
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : ok
  Block Sequential    : ok
  Checkerboard        : ok
  Bit Spread          : ok
  Bit Flip            : ok
  Walking Ones        : ok
  Walking Zeroes      : ok
  8-bit Writes        : ok
  16-bit Writes       : ok

Loop 2/3:
  ...
Loop 3/3:
  ...

Test de Mémoire sur Microcontrôleur (MCU)

La version MCU de memtester est une adaptation simplifiée du code source Linux.

Étape 1 : Acquisition du Code Source

$ git clone https://github.com/surez-ok/mcu_toolset.git

Étape 2 : Accès au Répertoire MCU

$ cd mcu_toolset/memtester/mcu

Étape 3 : Intégration et Exécution sur la Plateforme Cible

Pour utiliser l'API de test mémoire sur un microcontrôleur, il faut fournir l'adresse physique de début du test, la taille de la zone mémoire à tester en octets, et le nombre de cycles d'exécution. Il est impératif de désactiver le cache de données (D-cache) sur le MCU avant d'exécuter le test. Si le D-cache est actif, les opérations de lecture/écriture pourraient ne concerner que le cache et non la DDR elle-même, faussant ainsi les résultats du test.

#include <stddef.h> // Pour size_t

// Déclaration de la fonction de test (peut varier selon l'implémentation exacte)
extern int memtester_mcu(unsigned long start_address, size_t test_size_bytes, unsigned int num_loops);

int main(void) {
    // Avertissement crucial : Le cache de données (D-Cache) doit être désactivé
    // pour garantir que les tests s'effectuent directement sur la DDR.
    // Sinon, les opérations pourraient ne cibler que le cache, faussant les résultats.
    // Votre code ici pour désactiver le D-Cache.

    unsigned long adresse_physique_ddr = 0x80000000UL; // Exemple : Adresse de début de la DDR
    size_t taille_a_verifier = 4096;                   // Tester 4 KB de mémoire
    unsigned int iterations_test = 5;                  // Exécuter 5 cycles de test

    // Appel de la routine de test mémoire
    int resultat_verification = memtester_mcu(adresse_physique_ddr, taille_a_verifier, iterations_test);

    if (resultat_verification == 0) {
        // La vérification s'est terminée sans erreurs
        // Ici, vous pourriez ajouter un journal ou un indicateur de succès.
    } else {
        // Des erreurs ont été détectées pendant la vérification de la mémoire.
        // Ici, vous pourriez ajouter un journal ou un indicateur d'échec.
    }

    return 0;
}

Étiquettes: DDR Microcontrôleur Test Mémoire memtester systèmes embarqués

Publié le 25 juillet à 09h17