Arduino et ses mémoires

La mémoire est l’un des principaux composants d’un ordinateur ou d’un microcontrôleur comme l’Atmega, coeur de l’arduino.

Nous allons examiner les 3 types de mémoires disponibles au sein d’un arduino uno, leurs capacités et  leurs rôles afin d’en comprendre les nuances et usages.
Cet article a pour objet  la présentation très synthétique de ce vaste sujet, nous évoquerons aussi quelques pistes pour résoudre les problèmes de manque de mémoire…

Les principales caractéristiques d’une mémoire sont  :

  • sa capacité de stockage en kilooctet (ko – 210 octets) ou en gigaoctet (Go – 230 octets) pour un pc de bureau,
  • sa vitesse en lecture et écriture (mégaoctet par seconde : Mb/s),
  • sa capacité à conserver les données dans le temps avec ou sans alimentation électrique,
  • son nombre de cycle d’écriture avant obsolescence.

Les 3 types de mémoires qui coexistent au sein d’un arduino Uno à base ATmega328 sont :

  • La mémoire FLASH : Peu coûteuse cette mémoire sert à stocker les programmes à exécuter, c’est une mémoire qui perdure après arrêt de l’alimentation. Rapide, elle est donnée pour une capacité de 1 000 000 de cycles. L’atmega 328 en est doté de 32 kilos (d’où la référence 32..8)
  • La mémoire SRAM (Static Read Access Memory) : Coûteuse mais rapide, cette mémoire sert à stocker des données temporaires (les variables de votre programme par exemple). C’est une mémoire volatile. Votre arduino uno en possède seulement 2kilos, c’est peu et c’est probablement de là que naîtrons vos premiers soucis de mémoire…
  • La mémoire EEPROM : (Electrically-Erasable Programmable Read-Only Memory ou mémoire morte effaçable électriquement et programmable)
    Elle permet le stockage par votre programme de données persistantes, peut coûteuse, mais lente, l’atmega 328 en possède 1 kilooctet. Cette mémoire s’use plus rapidement, sa capacité esr de 100 000 cycles d’écriture. Cette mémoire permettra à vos programmes de stocker des données de log ou des états devant être conserver de manière pérenne (après arrêt de l’alimentation)

La lecture d’une mémoire ne « l’use pas», seul les cycles d’écriture contribuent à son usure progressive.
Le tableau ci-dessous vous présente les capacités mémoire de l’Arduino en fonction du microcontrôleur utilisé.

arduino-memoires

 

Utilisation de la mémoire Flash

Lors de la compilation de votre code, l’IDE vous donne une indication sur la mémoire Flash utilisée par votre programme. Si vous dépassez la capacité de votre microcontrôleur vous en serez immédiatement informé. Pas de mauvaise surprise de ce côté-là…
Information sur l’utilisation de la mémoire Flash (8 kilos/ 32 dans l’ exemple ci-dessous)

memoire-flash-ide-arduino

Utilisation de la SRAM

Le microcontrôleur organise cette mémoire pour stocker des données d’usages différents, l’espace est découpé en 3 zones non « fixes » pour :

  • conserveur les valeurs de vos variables statiques ou globales. Cette zone est la « static data / données statiques ». Elle est stockée en « fin de mémoire »
  • stocker les variables temporaires, déclarées en cours d’exécution de votre programme. On parle du Heap ou Tas. Cette zone occupe une place croissante, elle se situe juste après la zone allouée aux variables statiques.
  • stocker les appels de fonctions, les interruptions, cette zone appelée stack ou pile va grossir à partir du début de la mémoire.

heap-sram

Attention :  la sram est très limités (2ko) et aucun contrôle n’est fait pour empêcher le débordement de ces zones entre elles.

Si cela se produit vous aurez droit à un crash de votre application sans plus d’informations. Ce crash sera de plus relativement aléatoire et risque de se traduire par un comportement complétement incohérent et anarchique de votre programme.

Vous pouvez à tout moment contrôler la quantité de SRAM encore libre avec la fonction ci-dessous.

int freeRam ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

La EEPROM

C’est à vous de gérer cette mémoire en spécifiant les octets à écrire dans les adresses mémoire. Pas de mauvaise surprise sauf erreur de programmation, vous pouvez aussi vérifier par une relecture que l’adresse mémoire ou vous avez écrit est encore valilde, si ce n’est pas le cas chaque relecture donnera un nombre aléatoire… (rappel : durée de vie d’une adresse mémoire eeprom : 100 000 cycles)

#include <EEPROM.h>

int adr=10; // adresse mémoire ou écrire (en octet à partir de 0)
int val=55 ; // valeur à écrire dans l’adresse mémoire 0 à 255
// Ecrit la valeur dans l’EEPROM.
// cette valeur est conserve après arrêt
// temps écriture 3.3S (Attention : max 100 000 écriture par adresse mémoire)
EEPROM.write(adr, val);

Les solutions possibles au manque de mémoire

1/ Optimisez la taille de vos variables et libérer l’espace mémoires lorsqu’elles ne servent plus (malloc / free)
2 / Utilisez une partie de la mémoire Flash pour stocker vos données statiques, lors de la déclaration de votre tableau préciser son stockage en flash grâce à l’instruction PROGMEM (librairie <avr/pgmspace.h> )
Plus d’info : http://arduino.cc/en/Reference/PROGMEM
3 / Ajouter de la mémoire de stockage via un lecteur de carte SD, il existe 2 types de formatage : compatible ou non avec un PC.
4 / Ajouter une eeprom pouvant être adressé en spi (le plus rapide) ou i2c : ces mémoires sont très bon marché, vous trouverez un bon exemple de mise en oeuvre à cette adresse : zem.fr

Références
Article très complet sur Afafruit (en anglais) : https://learn.adafruit.com/memories-of-an-arduino/arduino-memories par Bill Earl
Plus d’info sur l’ATmega : http://www.reality.be/elo/labos2/files/AtMega32DocFr.pdf
Blog Eskimon : http://eskimon.fr/1397-arduino-annexe-2-gestion-de-la-memoire
Blog Plain DSP : http://www.plaindsp.com/memory-issue/

Pour aller plus loin
Gestion de l’écriture dans l’eeprom avec la technique du wear leveling permettant de répartir les cycles d’écriture afin d’avoir une usure « homogène » de la mémoire.

Laisser un commentaire