Forum: Mikrocontroller und Digitale Elektronik Atmel 1284p Data Register überschrieben


von Thomas D. (blackworker)


Lesenswert?

Hi,

ich programmiere einen Atmel 1284p mit dem Atmel-Studio 6 und steuere 
dabei ein OLED-Display (SEPS525) an.

Dabei habe ich mir einen eigenen Zeichensatz erstellt mit dem ich die 
Zahlen 0-9 ausgeben kann.

Diesen Zeichensatz speichere ich in Arrays auf dem uC ab:
1
volatile uint8_t NumberArray_1[] =
2
  {
3
    /*----------------------------------------
4
    ;hexcode: 0031
5
    ;width x height: 16 x 24
6
    ;size: 48 bytes
7
    ------------------------------------------*/
8
    48, 16, 24,
9
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10
    0x01, 0x80, 0x01, 0x80, 0x0F, 0x80, 0x0F, 0x80,
11
    0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
12
    0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
13
    0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0,
14
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15
  };
16
  
17
  volatile uint8_t NumberArray_3[] =
18
  {
19
    /*----------------------------------------
20
    ;hexcode: 0033
21
    ;width x height: 13 x 24
22
    ;size: 39 bytes
23
    ------------------------------------------*/
24
    39, 14, 24,
25
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8,
26
    0x1F, 0xE0, 0x83, 0x80, 0x0C, 0x00, 0x60, 0x06,
27
    0x01, 0xE0, 0x0F, 0x00, 0x0C, 0x00, 0x30, 0x01,
28
    0x80, 0x0C, 0x00, 0x61, 0x06, 0x0F, 0xF0, 0x3E,
29
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30
  };
31
32
.....usw

Beim Debuggen sehe ich das dieses Array "NumberArray_3" auf die Adresse 
0x4079 (fortlaufend) abgespeichert wird.
Nun passiert im Laufe des Programms, dass einzelne Werte der Adressen 
des Arrays mit irgendwelchen Zahlen überschrieben werden obwohl absolut 
nicht (weder lesend/schreibend) auf das Array zugegriffen werden soll.

Wenn ich nun auf das "NumberArray_3" lesend zugreife (um eine Zahl auf 
dem Display auszugeben), dann kommt natürlich nur Müll raus

Interessanterweise trifft dies aber nur bei der Zahl 3 zu - alle andere 
Zeichen werden korrekt ausgegeben.

Meine Frage lautet: Wie kann es in dem uC passieren, dass einfach 
verschiedene Werte von bereits initialisierten Arrays überschrieben 
werden??

Compiler-Optimierung hab ich von -O0 bis -Os alles durchprobiert - keine 
Veränderung.

Auch sollte ich noch genügend freien Speicher haben
1
Task "RunCompilerTask"
2
    C:\Program Files (x86)\Atmel\Atmel Studio 6.1\shellUtils\make.exe all 
3
    make: Nothing to be done for `all'.
4
  Done executing task "RunCompilerTask".
5
  Task "RunOutputFileVerifyTask"
6
        Program Memory Usage   :  2894 bytes   2,2 % Full
7
        Data Memory Usage     :  502 bytes   3,1 % Full
8
  Done executing task "RunOutputFileVerifyTask".

Ich suche schon seit 8 Stunden den Fehler und bin mitterlweile absolut 
ratlos und weiß nicht weiter...

Kennt jemand die Ursache für dieses Symptom?

mfg

von Klaus W. (mfgkw)


Lesenswert?

Das kann über Zeigerarithmetik fast überall passieren, z.B. indem auf 
ein davor liegendes Feld mit einem zu großen Index zugegriffen wird oder 
auf ein dahinter liegendes mit einem zu kleinen Index (ein negativer 
Index ist kein Problem).
Beliebt ist auch, über einen nicht initialisierten Zeiger auf Speicher 
zuzugreifen.

Was es bei dir genau ist, sieht man natürlich nicht mangels Quelltext.

von NurEinGast (Gast)


Lesenswert?

Ich glaube so wirst Du nicht viel sinvolle Hilfe bekommen.
Zeig doch mal den Rest des Programmes.

In NumberArray_3[] steht als Kommentar ";size: 39 bytes"
Im Array sind aber 39+3 Bytes drin.
Das sagt noch nichts. Wir wissen nicht was Du mit dem Array machst.
Deutet aber schon mal drauf hin, dass etwas mit den Arraygroessen und 
Zuggriffen nicht stimmen könnte.

Ohne weitere Info - keine Idee.

von Thomas D. (blackworker)


Angehängte Dateien:

Lesenswert?

NurEinGast schrieb:
> Ich glaube so wirst Du nicht viel sinvolle Hilfe bekommen.
> Zeig doch mal den Rest des Programmes.
>
> In NumberArray_3[] steht als Kommentar ";size: 39 bytes"
> Im Array sind aber 39+3 Bytes drin.
> Das sagt noch nichts. Wir wissen nicht was Du mit dem Array machst.
> Deutet aber schon mal drauf hin, dass etwas mit den Arraygroessen und
> Zuggriffen nicht stimmen könnte.
>
> Ohne weitere Info - keine Idee.


Jo, ich hab mal mein gesamtes Projekt gepackt und hochgeladen, es ist 
etwas umfangreich, deswegen wollte ich es am Anfang nicht gleich 
mitgeben falls es sich um was ganz triviales handelt.

In Zeile 47 von TempSensor.cpp wird das erste mal die Methode aufgerufen 
die die Zahlen "321" ausgibt.

Nur die Ziffer 3 wird fehlerhaft ausgegeben, alle andere Zahlen passen.

Der Kommentar  ";size: 39 bytes" bezieht sich auf die Nutzdaten, welche 
die Zahl darstellen.

Die 3 Bytes davor geben meiner Ausgabefunktion Informationen, aus 
wievielen Bytes die Ziffer besteht, wie Breit und wie Hoch diese ist. 
Alles nachfolgende stellt die Ziffer an sich dar.

Allerdings vermute ich dass das wenig mit dem Fehler zu tun hat, denn 
alle Ziffern werden über dieselbe Funktion ausgegeben - und nur bei der 
"3" tritt der Fehler auf.

Ich lasse mich aber sehr sehr gern eines besseren belehren! :)

von da1l6 (Gast)


Lesenswert?

Hallo

Ich würde vorschlagen diese Arrays in den Flash (Progmem) zu verlagern, 
dort werden sie garantiert nicht überschrieben und der RAM wird nicht 
belegt.

RAM ist bei AVRs knapp und die Fehlerbeschreibung klingt so als wäre er 
dir bereits ausgegenagen.

da1l6

von Thomas D. (blackworker)


Lesenswert?

da1l6 schrieb:
> Hallo
>
> Ich würde vorschlagen diese Arrays in den Flash (Progmem) zu verlagern,
> dort werden sie garantiert nicht überschrieben und der RAM wird nicht
> belegt.
>
> RAM ist bei AVRs knapp und die Fehlerbeschreibung klingt so als wäre er
> dir bereits ausgegenagen.
>
> da1l6

Hi da116,

super, danke für den Denkanstoß :)

RAM hab ich laut Datenblatt 16kB, ich dachte das der Compiler eventuell 
eine Warning ausgibt falls es dort zu absehbaren Engpässen kommt (??) 
Daran hab ich nicht gedacht.

Das worauf du abzielst bezieht sich auf das hier, richtig?
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

Gibt es Vor/Nachteile zwischen progmem/__flash ?

Ich probiers nach ein wenig Schlaf gleich mal aus und berichte ob es 
daran lag - Vielleicht ist es ja eine Hilfestellung für andere Personen

mfg

von Karl H. (kbuchegg)


Lesenswert?

Thomas D. schrieb:

> super, danke für den Denkanstoß :)

Nein ist es nicht.

Du hast definitiv im Programm irgendwo einen Schreibzugriff, der nicht 
so sein sollte. Mit der verlagerung dieser Daten ins Flash, verschiebst 
du nur das Problem, aber du löst es nicht.
Anstelle deiner Font-Daten wird eben dann irgendwas anderes im Speicher 
niedergebügelt.

Solche Probleme müssen GELÖST werden und nicht KASCHIERT!

Sei froh, dass du einen reproduzierbaren Fall hast, mit dem du 
feststellen kannst, ob eine Änderung im Programm (die kann ganz woanders 
sein), das Problem jetzt gelöst hat oder nicht! Einen Fehler 
reproduzierbar zu haben ist das Um und Auf beim Debuggen. Zerstör dir 
diese Reproduzierbarkeit jetzt um keinen Preis noch nicht. Wenn du den 
eigentlichen Fehler gefunden hast, DANN ist es Zeit über eine 
Verlagerung ins Flash nachzudenken. Aber nicht jetzt. Jetzt muss erst 
mal der fehlerhafte Zugriff gefunden werden.

von Thomas D. (blackworker)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Thomas D. schrieb:
>
>> super, danke für den Denkanstoß :)
>
> Nein ist es nicht.
>
> Du hast definitiv im Programm irgendwo einen Schreibzugriff, der nicht
> so sein sollte. Mit der verlagerung dieser Daten ins Flash, verschiebst
> du nur das Problem, aber du löst es nicht.
> Anstelle deiner Font-Daten wird eben dann irgendwas anderes im Speicher
> niedergebügelt.
>
> Solche Probleme müssen GELÖST werden und nicht KASCHIERT!
>
> Sei froh, dass du einen reproduzierbaren Fall hast, mit dem du
> feststellen kannst, ob eine Änderung im Programm (die kann ganz woanders
> sein), das Problem jetzt gelöst hat oder nicht! Einen Fehler
> reproduzierbar zu haben ist das Um und Auf beim Debuggen. Zerstör dir
> diese Reproduzierbarkeit jetzt um keinen Preis noch nicht. Wenn du den
> eigentlichen Fehler gefunden hast, DANN ist es Zeit über eine
> Verlagerung ins Flash nachzudenken. Aber nicht jetzt. Jetzt muss erst
> mal der fehlerhafte Zugriff gefunden werden.

Da stimm ich dir vollkommen zu. Also du bist davon überzeugt das der 
Speicherbereich von den Daten-Arrays nicht durch "zu wenig RAM" 
manipuliert wird, sondern das im Programm explizit darauf 
zugegriffen/geschrieben wird?

Soweit ich das beurteilen konnte wurde immer derselbe Speicherbereich 
verändert, in dem warscheinlich durch Zufall immer das Daten-Array für 
die Ziffer "3" stand.
Kann ich mir beim Debugging irgendwie anzeigen lassen welche Zeiger 
aktuell auf eine bestimmte Adresse zeigen?

mfg

von NurEinGast (Gast)


Lesenswert?

Sagt mal .......

Im constructor werden Variablen
   "volatile uint8_t NumberArray_0[]"
   "volatile uint8_t NumberArray_1[]"  etc.
definiert und initialisiert.

Diese Variablen sind nur im constructor definiert.
In der Klassendefinition nicht.

Nun wird die Variable initialisiert und (deren Pointer) in ein anderes 
Array kopiert.
              this->NumberArray[0] = NumberArray_0;

Nun wird der constructor verlassen, die Variablen aber weiter verwendet.
( Über das this->NumberArray[] )

Dann kann doch nicht gut gehen ? Oder ?

von Karl H. (kbuchegg)


Lesenswert?

In SEPS525.cpp

Im Kontruktor
1
SEPS525::SEPS525()
2
{
3
  /////////////////////////////////////
4
  //Initialisize the Array of Numbers//
5
  /////////////////////////////////////
6
  volatile uint8_t NumberArray_0[] = 
7
8
...
9
  
10
  volatile uint8_t NumberArray_1[] =
11
12
...
13
14
  volatile uint8_t ZeichenArray_1[]=
15
16
...
17
18
  this->ZeichenArray[0] = ZeichenArray_1;
19
  
20
  this->NumberArray[0] = NumberArray_0;
21
  this->NumberArray[1] = NumberArray_1;
22
  this->NumberArray[2] = NumberArray_2;
23
  this->NumberArray[3] = NumberArray_3;
24
  this->NumberArray[4] = NumberArray_4;
25
  this->NumberArray[5] = NumberArray_5;
26
  this->NumberArray[6] = NumberArray_6;
27
  this->NumberArray[7] = NumberArray_7;
28
  this->NumberArray[8] = NumberArray_8;
29
  this->NumberArray[9] = NumberArray_9;
30
  
31
  this->ptr_NumberArray = this->NumberArray;
32
  
33
} //SEPS525

Junger Mann.
Deine Arrays hier im Konstruktor sind alle funktionslokale Variablen. 
D.h. nach Beendigung der Funktion existieren diese nicht mehr. Du hast 
dir soeben im Konstruktor Pointer auf Objekte gemerkt, die nicht mehr 
vorhanden sind, wenn du sie brauchst. In der Zwischenzeit ist aber der 
Speicher schon wieder für was weiß ich alles benutzt worden. Kein 
Wunder, dass du deine Daten da drinnen nicht mehr wiederfindest.

von Thomas D. (blackworker)


Lesenswert?

NurEinGast schrieb:
> Sagt mal .......
>
> Im constructor werden Variablen
>    "volatile uint8_t NumberArray_0[]"
>    "volatile uint8_t NumberArray_1[]"  etc.
> definiert und initialisiert.
>
> Diese Variablen sind nur im constructor definiert.
> In der Klassendefinition nicht.
>
> Nun wird die Variable initialisiert und (deren Pointer) in ein anderes
> Array kopiert.
>               this->NumberArray[0] = NumberArray_0;
>
> Nun wird der constructor verlassen, die Variablen aber weiter verwendet.
> ( Über das this->NumberArray[] )
>
> Dann kann doch nicht gut gehen ? Oder ?

Zefix, grad kam mir was ins Hirn geschossen.

Ist es möglich dass ich durch diese "Initialisierung" den Speicher der 
Arrays nach Verlassen des Konstruktors wieder freigegeben habe ??!

Ich dachte da ein Zeiger darauf existiert bleibt dieser fest reserviert?

von Thomas D. (blackworker)


Lesenswert?

Karl-Heinz!!! 1000 Dank für den Hinweis, wie kann man nur so blöd 
sein...

Manchmal sieht man den Wald vor lauter Bäumen nicht, gepaart mit 
jugendlichen Leichtsinn und zuviel Java-Programmierung.

Ich geh mich jetzt schämen....


mfg ;)

von Karl H. (kbuchegg)


Lesenswert?

Thomas D. schrieb:

> Zefix, grad kam mir was ins Hirn geschossen.
>
> Ist es möglich dass ich durch diese "Initialisierung" den Speicher der
> Arrays nach Verlassen des Konstruktors wieder freigegeben habe ??!
>
> Ich dachte da ein Zeiger darauf existiert bleibt dieser fest reserviert?

Sei mir nicht böse.
Aber das ist 'Lebensdauer von Variablen' - Kenntnisstufe 0.9

Funktionslokale Variablen, werden innerhalb der Funktion erzeugt und bei 
Verlassen der FUnktion wieder zerstört

1
void foo()
2
{
3
  int i;
4
5
  for( i = 0; i < 8; i++ )
6
   ;
7
}

i existiert nur solange, solange die Funktion läuft. Wird die Funktion 
beendet, dann wird die Variable zerstört (ihr Speicher zur weiteren 
Benutzung wieder freigegeben).
Warum soll ein Pointer daran was ändern? Wann soll denn dann der 
Speicher wieder freigegeben werden?
In C++ gibt es keinen 'Speicher Managemenet ist so kompliziert, drumm 
brauch ich eine Garbage Collection die hinter mir aufräumt' Mechanismus.

: Wiederhergestellt durch User
von NurEinGast (Gast)


Lesenswert?

bin dann ma weg ....

von Thomas D. (blackworker)


Lesenswert?

Völlig korrekt. Ich habe zuerst C dann C++ gelernt danach kam lange Zeit 
Java, C#....

Die virtuelle Maschine hat mich versaut....

von c-hater (Gast)


Lesenswert?

Thomas D. schrieb:

> Meine Frage lautet: Wie kann es in dem uC passieren, dass einfach
> verschiedene Werte von bereits initialisierten Arrays überschrieben
> werden??

Ganz einfach: Indem man Scheiße programmiert.

> Auch sollte ich noch genügend freien Speicher haben

Das nützt rein garnix, wenn wegen eines Bugs in deinem Programm 
eigentlich belegter Speicher überschrieben wird.

> Kennt jemand die Ursache für dieses Symptom?

Nahezu immer das Teil vor dem Monitor. Sehr viel seltener Fehler in 
Compilern, Assemblern oder der Hardware.

von Klaus W. (mfgkw)


Lesenswert?

Prima!

Nachdem alle anderen hier nicht die leiseste Ahnung haben, wo das 
Problem liegen könnte, hast du als erster einen hilfreichen Beitrag 
geliefert.

Das ist natürlich mein Vorschlag für den "Beitrag des Monats".

von C-hater-hater (Gast)


Lesenswert?

Richtige Programme kann man sowieso nur in ASM schreiben. Nur so ist 
sichergestellt, daß nichts durch den C-Compiler falsch gemacht werden 
kann und auch das (temporäre) nichtbeherschen der Sprache C keine 
Probleme verursacht.
Im konkrete Fall würde ja schon das Schreiben einer simplen Java-VM das 
ursprüngliche Problem lösen. Dann würden Java-like Arrays funktionieren.
(wer Ironie findet, darf sie behalten)

von holger (Gast)


Lesenswert?

>Richtige Programme kann man sowieso nur in ASM schreiben.

Der Pausenclown ist wieder da! Ich freu mich so;)
Wie geht dir? Wie wars beim Psychater?

von C-hater-hater (Gast)


Lesenswert?

Bitte Namen lesen und verstehen!

von Spess53 (Gast)


Lesenswert?

Hi

>Bitte Namen lesen und verstehen!

Keine Entschuldigung für soziale Inkompetenz.

MfG Spess

von C-hater-hater (Gast)


Lesenswert?

Was ist die soziale Imkompetenz bei der ironischen Überspitzung der 
typischen Aussage des Kollegen "c-hater" unter Verwendung eines 
nicknames, der klarstellt, was ich von c-hater halte?
Oder gilt: c-hater==spess53==holger ?

von holger (Gast)


Lesenswert?

>>Bitte Namen lesen und verstehen!
>
>Keine Entschuldigung für soziale Inkompetenz.

Die Auflösung:

Post von C-hater
Bla bla bla

Und dann
C-hater-hater

Also jemand der C-hater
nicht mag;)

von C-hater-hater (Gast)


Lesenswert?

Danke Holger!
BTW, nicht die Person, die kenne ich ja garnicht, sondern wie sie ihre 
externe Meinung vertritt.

von c-hater (Gast)


Lesenswert?

C-hater-hater schrieb:

> Was ist die soziale Imkompetenz bei der ironischen Überspitzung der
> typischen Aussage des Kollegen "c-hater" unter Verwendung eines
> nicknames, der klarstellt, was ich von c-hater halte?

Wenn du lesen könntest, dann wöre dir aufgefallen, daß es in meinem 
Posting überhaupt nicht um C ging.

Es ging vielmehr darum, daß vor allem unerfahrene Programmierer dazu 
neigen, die Fehler zuallerletzt im eigenen Code zu suchen.

von Klaus W. (mfgkw)


Lesenswert?

c-hater schrieb:
> Es ging vielmehr darum, daß vor allem unerfahrene Programmierer dazu
> neigen, die Fehler zuallerletzt im eigenen Code zu suchen.

... und das wiederum war gar nicht das Problem des TO.

Wenn du lesen könntest, wäre dir das vielleicht aufgefallen :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.