[Aide] Gestion de la mémoire vive

Bonjour à tous,
J'utilise une Arduino Uno R3 avec un ATMEGA328P.
Si je ne me trompe pas, je dispose donc de 2048 bytes de SRAM.

J'ai un programme qui utilise la mémoire suivante:
Buffer Serial = 256 bytes. (j'ai modifié la library)
SERIN[200]= 200 bytes.
Chaine de caractère pour affichage sur LCD = 24 bytes.
variables type bytes divers = 10 bytes.
soit un total il me semble de 490 bytes.
Et là, mon programme fonctionne correctement.
Si j'ajoute un array SERINMODIF[92] soit 92 bytes supplémentaires, mon programme ne fonctionne plus, comme si j'avais un écrasement mémoire.
Si quelqu'un a une idée ? peut être mon calcul de la mémoire est il faut ?
Merci de votre aide.
Philippe.

Bonjour,

Il faut aussi prendre en compte :

  • les divers registres cpu et variables bas niveau de gcc
  • le stack (la pile) qui stocke les adresses de retour des appels de fonctions (taille variable)
  • les variables locale + les variables global
  • Serial se compose de deux buffer (Rx et Tx) -> tu as alloué 256 octets pour les deux ou juste pour un ?

Le fait d'avoir modifié la taille du buffer série et d'avoir une variable SERIN (serial in ?) ne présage rien de bon qu'en au code.
Sans ton code on ne peut pas deviner ou est le probléme :wink:

Sinon pour être fixer sur la mémoire ram dispo à un moment t :
http://arduino.cc/playground/Code/AvailableMemory

j'ai remplacé la variable SERIN par PATCHIN. le problème reste le même.

Mon code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(18,19,14,15,16,17);

const byte patchreq[11] = {0xF0, 0x0, 0x21, 0x02, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0xF7};
byte PATCHIN[200];
byte PATCH[92];
byte i = 0;
byte a = 0;
byte index = 0;
byte checksumlu = 0;
byte checksum = 0;
byte b=0;

void setup()
{
Serial.begin(31250);

lcd.begin(16,2);
lcd.clear();
lcd.print("o0o FACTORY");
lcd.setCursor(0,1);
lcd.print("Serial SysEx ");
delay(100);
lcd.clear();
}

void loop()
{
patchread();
lcd.print(a);
lcd.print(" ");
lcd.print(PATCHIN[0], HEX);
lcd.print(" ");
lcd.print(PATCHIN[194], HEX);
lcd.print(" ");
lcd.print(checksumlu, HEX);
lcd.print(" ");
lcd.print(checksum, HEX);

loop:
goto loop;
}

void patchread()
{
Serial.flush();
Serial.write(patchreq,11);

while(Serial.available() < 205)
{
}

do {
i = Serial.read();
}
while(i != 0xf7);

index = 0;
do
{
PATCHIN[index] = Serial.read();
index++;
}
while(PATCHIN[index] != 0xf7);

checksumlu = PATCHIN[192];
checksumlu *= 16;
checksumlu += PATCHIN[193];

checksum = 0;
for (index = 0; index < 92; index++)
{
i = (index * 2) + 8;
b = (PATCHIN * 16) + PATCHIN[(i+1)];

  • PATCH[index] = b; // This line causes the problem <<<--------------------------------------------------*
  • checksum += b;*
  • } *
  • a=PATCHIN[10];*
    _ a *= 16;_
  • a += PATCHIN[11];*
    }

Les tableaux ou chaînes de caractères initialisés dans une fonction ou aun niveau global sont à proscrire absolument car cela utilise de la ram.

Il faut utiliser PROGMEM afin d'écrire ces constantes dans la mémoire programme flash.

Tout est expliqué dans la doc Arduino.

JLB

Bonjour,

Merci de mettre le code source entre balise code (# dans l'éditeur) :wink:
Je voie des choses qui ne devrait pas exister dans ton code ! :wink:

Tu utilises des variables globale ... mais elles ne sont accédées que dans une seule fonction (loop) -> c'est inutile et dangereux.

Ensuite je voie :

while(Serial.available() < 205)
{
}

do {
i = Serial.read();
}
while(i != 0xf7);

Pourquoi avoir augmenter la taille du buffer série pour faire cela !?

Alors qu'il suffirai de faire :

do {
while(Serial.available() < 1);
i = Serial.read();
}
while(i != 0xf7);

Ensuite je vois une erreur simple, mais fatale :

 index = 0;
  do
  {
    PATCHIN[index] = Serial.read();
    index++;
  } 
  while(PATCHIN[index] != 0xf7);

Et si jamais index vient à dépasser la valeur 199 ?
-> Buffer overflow = écriture dans des zones mémoires partagé, bug incompréhensible, reset intempestif si on tape dans un registre cpu, ...

Une ligne à ajouter :

 index = 0;
  do
  {
    while(Serial.available() < 1);          
    PATCHIN[index] = Serial.read();
    if(++index == 200) return; // Erreur de taille du buffer -> Quitte loop() ce qui recommence un nouveau loop()
  } 
  while(PATCHIN[index] != 0xf7);

Ensuite :

  checksumlu = PATCHIN[192];
  checksumlu *= 16;
  checksumlu += PATCHIN[193];

checksumlu est un byte, donc de valeur comprise entre 0 et 255 !
Tu devrais travailler ici avec un int, de même pour i, b et a :wink:

Merci @skywodd pour toutes ces remarques pertinentes et constructives. Je vais revoir mon code.

Pour le checksum, j'utilise un byte car il doit être modulo 256.

phm78:
Pour le checksum, j'utilise un byte car il doit être modulo 256.

modulo 256 -> (valeur % 256) :wink: