Forum: Compiler & IDEs Externes Ram: printf() - Problem


von Andreas Paulin (Gast)


Angehängte Dateien:

Lesenswert?

Habe ein externes SRAM an ATMEGA angebunden.
60kb zur Verfügung.

ExRam nur als Heap, daher erst in main() die Freischaltung:
1
// mit Waitstates:
2
MCUCR |= (1<<SRE)|(1<<SRW10);    
3
XMCRA |= (1<<SRW11);        // the number of wait-states
4
XMCRB |= (1<<XMBK);

Nur: Die Testroutine, die ich dafür geschrieben habe zeigt ein 
merkwürdiges Verhalten.
Der Test läuft so:
- Ein Pointer 'pExRam' wird mit '__malloc_heap_start' (1100h) 
initialisiert
- Dann bis '__malloc_heap_end' (FFFFh)hochgezählt.
- Jede Speicherzelle '*pExRam' wird einmal mit 55h und mit AAh 
beschrieben, gelesen und gecheckt.

Damit der Test nicht bereits verwendete Zellen des Heap korrumpiert, 
wird
- zuerst der Wert gesichert
- dann getestet
- dann der ursprüngliche Wert zurückgeschrieben

Der Test läuft einwandfrei von 1100h bis FFFFh.

Seltsamerweise verschluckt sich der ATMEGA128 an printf()-Aufrufen 
innerhalb der Testschleife, wenn der Format/Ausgabestring
"etwas länger" wird. Siehe Codeauszug...
Heißt dann: Kiste steht, nichts geht mehr, bestenfalls Neustart..
Aber: 'printf()' wird immer erst aufgerufen, NACHDEM die Speicherzelle 
gecheckt UND der ursprüngliche Inhalt wieder restauriert wurde....

????
Codeauszug anbei.

Der RAMcheck läuft auch ohne printf(), aber trotzdem: Hat jemand einen 
Tip für mich, wo der Hund begraben liegen könnte?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Womit hast du denn stdout angelegt?  (fdevopen, fdev_setup, FDEV_SETUP)

von Andreas Paulin (Gast)


Lesenswert?

Ich habs mit dem Macro angelegt:
1
#ifndef STDIO_DEFINED  
2
  #define STDIO_DEFINED
3
  static FILE uart0_stream = FDEV_SETUP_STREAM(uart0_putchar, uart0_getchar, _FDEV_SETUP_RW);
4
  static FILE uart1_stream = FDEV_SETUP_STREAM(uart1_putchar, uart1_getchar, _FDEV_SETUP_RW);
5
#endif  
6
if (UartNum==0)
7
  {
8
  stdout = &uart0_stream;
9
............

Meines Wissens wird da nichtmal malloc() verwendet.
Und selbst WENN printf() auf das ExRam zugreift: Der Speicherzellentest 
AN SICH ist sehr kurz, außerhalb jedes printf-Aufrufes und transparent, 
also zerstört nicht den Zelleninhalt:
ucTemp1=*pExRam;
*pExRam=0x55;
ucTemp2=*pExRam;    // Inhalt zurücklesen
*pExRam=ucTemp1;    // alten Wert zurückschreiben

Hm.......

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andreas Paulin wrote:

> Meines Wissens wird da nichtmal malloc() verwendet.

Ja, darauf wollte ich auch hinaus.

Nee, dann habe ich aus der Kalten keine Idee, was da schief gehen
könnte.  Hast du 'ne Chance, das mit einem JTAG ICE nachzuvollziehen?

von Andreas Paulin (Gast)


Lesenswert?

Nein, ICE haben wir noch nicht.
Aber ist vielleicht mal ne gute Idee. Kost' 250 Steine, so'n Ding, und 
wenn ich überlege, wie oft ich schon tagelang wie Sherlock Holmes nach 
der Nadel im Heuhaufen gesucht habe.........

von Günter R. (galileo14)


Lesenswert?

Andreas Paulin wrote:
> Nein, ICE haben wir noch nicht.
> Aber ist vielleicht mal ne gute Idee. Kost' 250 Steine, so'n Ding, und
> wenn ich überlege, wie oft ich schon tagelang wie Sherlock Holmes nach
> der Nadel im Heuhaufen gesucht habe.........

Beim Elektronikladen (http://elmicro.com/de/avrjtag.html) gibt's so ein 
Ding (von Olimex) für EUR 45,70; ich bin damit super zufrieden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, das Olimex-Teil ist halt ein Clone vom JTAG ICE mkI.  Damit kannst
du (mal aus Industriesicht) nur noch alten Schrott debuggen.

Interessanter dürften die Bündel aus JTAG ICE mkII + STK500 sein, die
es jetzt 'ne Zeit lang bei den Atmel-Distris gab (Spoerle zum Bleistift,
wohl auch Ineltek), die gab's zusammen für was um die 150 Fragezeichen.

von Uhu U. (uhu)


Lesenswert?

Ändere doch mal deinen Speichertest so:

Allokiere mit malloc den größtmöglichen Speicherblock, der Heap sollte 
davor zwar initialisiert sein, aber noch nicht benutzt.

Dann laß deinen Test über diesen Speicherblock laufen.

Dabei kannst der Heapverwaltung nicht ungewollt in die Quere kommen und 
die testet dir andereseits zumindest einen großen Teil des für die 
Heapverwaltung benötigten Speichers.

von Andreas Paulin (Gast)


Lesenswert?

Ich habe das Problem gestern erstmal zurückgestellt, da der Ramcheck 
OHNE die printf-Statemenst einwandfrei durchlief. Prioritäten setzen!

Aaaaaaaaaaaaaaber:
Diese seltsamen Symptome hatte ich aber in ganz anderen Bereichen immer 
und immer wieder: Scheinbar irrelevante Codepartikelchen bringen die 
ganze Kiste zum Stehen
Hm.... Verdacht auf irgendwelche Speicherprobleme?
Schon.....
Habe dann meinen Widerwillen unterdrückt und mir mal das .MAP-File 
angesehen ächz WAS'n Gewurschtel. Ist ja echt ein Fall für'n Guru ;-)

Bin jetzt auch ein bischen Guru :) Das Ram war schlicht voll.
Die .data-Sektion reichte bis 0x00800dd0.
Ich hatte ein fettes, statisch deklariertes Array hatte ich vergessen, 
und die 4kB vom ATMEGA128 waren doch schon ziemlich voll......

Und ich denke, dass die langen printf-Strings über den Stack übergeben 
werden..? Und das war wahrscheinlich das Problem.

Habe das Array vorläufig mal rausgeschmissen, und plötzlich läuft alles 
schön rund :)
Memory checken!!

Hatte also nichts mit dem ext. SRAM zu tun, schien nur so........

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, die Mapfiles sind nur für Gurus, ich weiß gar nicht, warum die Leute
so auf diese Dinger stehen.  Eigentlich sind die nur nützlich für
jemanden, der am Linker oder den Linkerscripts arbeitet.

Das, was die meisten Leute als Map-Datei erwarten, ist beim GCC eher
die Symboltabelle.  Die bekommt man mittels avr-nm aus dem ELF-File
heraus.  Das WinAVR-Makefile müsste mittlerweile auch standardmäßig
eine Datei mit der Endung .sym damit anlegen.

von Andreas Paulin (Gast)


Lesenswert?

ja, herzlichen Dank für die Tips.
Habs jetzt hin- und herprobiert und es ist reproduzierbar einfach ein 
volles RAM.

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.