Forum: Compiler & IDEs Mega128 + gcc + 32k externes SRAM --> läuft nicht


von Timo Birnschein (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich versuche seit zweieinhalb Tagen relativ vergeblich meinen Mega128
mit 32K externes SRAM zu verbinden und in C zu verwenden.
Ziel der Übung ist es, eine GameBoy Camera auszulesen, das Bild zu
verarbeiten und anschließend erst über den rs232 Port zu jagen. Das ist
zum einen strukturierter und zum anderen deutlich weniger
Fehleranfällig, weil man sich sogar auf die Timings der Camera
konzentrieren kann und nicht auf die rs232 Übertragung warten muss.

So weit die Theorie, jetzt die Praxis:
Ich habe die Register gesetzt:
  MCUCR = 0x80;
  XMCRA = 0x00;
  XMCRB = 0x81;

Ich habe das Makefile geändert:
  EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x8090ff

Das Problem ist nun, dass der AVR seit der änderung im Makefile kein
Lebenszeichen mehr von sich gibt. Ich kann ihn allerdings mit was
anderem Programmieren, dann läuft er wieder.
Weil mich genau das sehr stutzig gemacht hat, bin ich mal auf die
andere Seite gegangen und habe mit Bascom die Funktion meines mehrfach
durchgemessenen RAMmoduls geprüft. Mit dem Ergebnis, dass das SRAM
tadellos funktioniert und mein Latch sogar ohne zusätzliche
wait-statements einwandfrei läuft.

Schreibe ich nun wieder mein C-Programm in den avr, regt sich wieder
nichts mehr. Ich weiß das, weil ich per RS232 debug-Messages ausgebe,
die nicht mehr erscheinen. Nichtmal die erste.

Vielleicht hat jemand von euch Zeit und Lust mir dabei zu helfen und
schaut sich mal meinen Quellcode an. Ich bin wirklich mit meinem Latein
am Ende, da ich schon seit über zwei Tagen nur an dem RAMmodul sitze und
es offenkundig hardwareseitig funktioniert.

Mein Programm sollte übersichtlich genug sein. Es gibt ein paar .h
Dateien die nicht mehr verwendet werden, aber das betrifft nicht den
compilierenden Teil.

Vielen Dank im Vorraus!

Gruß
Timo

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


Lesenswert?

Benutzt du die binutils 2.16?  Die haben einen Bug drin.

Ändere mal:

  EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x8090ff

in


EXTMEMOPTS=-Wl,--section-start=.data=0x801100,--defsym=__heap_end=0x8090 
ff

von Timo Birnschein (Gast)


Lesenswert?

ohaha, vielen Dank für die promte Antwort und dann auch noch von der
Sorte "geil es läuft"! :D

Also mit sowas habe ich natürlich nicht gerechnet. Die Version von
binutils kann ich dir nicht sagen. Ich habe mit die aktuelle Version
vom ProgrammersNotepad2 runtergeladen. Da war gcc bei. Das makefile
habe ich mir irgendwo aus einem example geholt und modiziert.

Jetzt wo du es sagst merke ich, dass das Makefile evtl noch von einer
erheblich älteren Version der Beispiele vom ProgrammersNotepad kommt.
Daran hatte ich garnicht gedacht! Ich werde das morgen prüfen, heute
ist mir leider die Luft aus.

Also ein neues Problem: Ich möchte ein array deklarieren (das ist auch
jetzt schon immer mein Speichertestarray und das soll 16768 einträge
lang sein.
Da sagt der compiler schonmal, dass der Speicher dazu nicht ausreicht.
Wenn ich das ding kleiner mache, also z.B. 4096, dann läuft der
compiler durch, allerdings kommt es beim durchlaufen der
SpeicherCheck-Funktion zu einem Pointerfehler.
Das sollte natürlich nicht passieren, denn ich hab ja nun 32kb
Speicher... normalerweise.

Evtl noch einen hint?

Danke schonmal, das hat mit schon sehr geholfen!

Timo

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


Lesenswert?

Sourcecode?

von Timo Birnschein (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist der Sourcecode.

Ich geh da nach dem Frühstück dran, aber vielleicht bist du ja zufällig
online und findest da direkt den fehler.

von Timo Birnschein (Gast)


Angehängte Dateien:

Lesenswert?

ok, vergessen wir den pointerfehler. Das war ein konstrukt der finsteren
Nacht.
Das Problem ist jetzt vielmehr, dass der µC wieder nicht läuft. Was
also gehstern mit den gleichen einstellungen noch ging, geht heute
nicht mehr. Ich verstehe das ehrlich gesagt nicht.
Ich habe deine Zeile im Makefile geändert, habe sogar ein makefile
eines aktuellen Beispiels genommen und modifiziert, aber mit den
gleichen Ergebnis.

Ich stelle hier nochmal den aktuellen, nicht startenden code online.
Wenn du da einen Blick reinwerfen könntest, wäre das super!

Gruß
Timo

von Timo Birnschein (Gast)


Lesenswert?

hm, also da muss immernoch ein fehler mit dem Makefile sein.
Und dass es gestern lief, muss leider auch ein Fehler gewesen sein,
denn heute macht der einfach garnichts mit den Einstellungen...

Der Cloue: Mit der Einstellung, dass nur der Heap im ext. Speicher
liegt (EXTMEMOPTS =
-Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x8090ff
) startet der Prozessor.
Der externe Speicher ist für mich allerdings nur sinnvoll, wenn ich
mein Bild-Array[128][123] da auslagern kann.

von Timo Birnschein (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jörg,

fröhliche Weihnachten gehabt zu haben!
Hast du evtl die Zeit gefunden dir das mal anzusehen?
Im Augenblick Programmiere ich das ganze mit Bascom, weil ich endlich
mal was sehen musste. Im Anhang befindet sich ein Screenshot von den
bisherigen Ergebnissen.
Ich bin an einem Punkt angelangt, an dem ich für die Camera eine
Belichtungsautomatik schreiben wollte. Dazu brauche ich weitere
Basic-Subroutienen. Leider hat Bascom scheinbar einen Bug, der
verhindert, dass man vernünftig funktionierende Stack-Größen definieren
kann, ohne dass sich die Stacks überschreiben...

Deswegen bin ich zu dem Schluss gekommen, dass um C kein Weg drum herum
geht. Der Compiler ist schlicht besser und vor allem deutlich
intelligenter als der Bascom-Compiler.
Leider geht das ohne das externe SRAM eben unter keinen Umständen, da
selbst die einfachste Bildbearbeitung auf dem AVR selbst unmöglich
wird, wenn kein Ram vorhanden ist, der wenigstens ein Bild speichern
kann.

Von daher wäre ich wirklich sehr glücklich darüber, wenn mir noch
weiter jemand hilft. Vielleicht gibt es ja eine triviale Lösung zu dem
Problem....

Vielen Dank fürs Lesen!

Timo

von castle (Gast)


Lesenswert?

hallo, ich übertrage die daten von der gameboycam gleich zum pc über
funk. dort werte ich die hindernisse aus mit purebasic und gebe dann
den robby ein steuersignal zum verhalten. die auswertung der daten ist
noch am anfang, gibt aber schon ergebnisse. der nachteil der gameboycam
ist, das der robby bei einer aufnahme anhalten muss, ist ein mangel der
gameboycam, das bild ist kein standbild. ansonsten ein interessantes
projekt mit dem avr16.
bei der cmucam2 klappt es besser, da wird die auswertung von der
camplatine durchgeführt und der avr bekommt daten (strings), die dann
sofort der avr16 bearbeiten kann, da ist mein erfolg schon bestens.
kostet 129 euro, lohnt sich wirklich.
die 3. möglichkeit bei mir läuft mit videocapture und einer cmoscam.
ein videobild vom robby wird zum pc gefunkt. dort lese ich ein bild aus
der zwischenablage mit purebasic aus und werte es in einer picturebox
aus. gibt auch schon ergebnisse.

castle

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


Lesenswert?

Tja, über Weihnachten war genügend anderes zu tun.

Jetzt habe ich mir das mal angeguckt.  Nachdem ich den Include von
<avr/timer.h> entfernt habe (die gibt's schon lange nicht mehr) und
im
Makefile noch -D__STDIO_FDEVOPEN_COMPAT_12 mit angegeben habe,
compiliert das Ganze auch gegen meine avr-libc 1.4.

Es gibt eine Warnung (außer den "this file has moved"-Warnungen
infolge der neueren avr-libc-Version), ansonsten compiliert es.

Ja, eine Variable muss beim AVR-GCC wohl kleiner als 32 KiByte sein,
ich denke, das hängt damit zusammen, dass die Indizierung des
Speichers über einen `int' erfolgt, also eine vorzeichenbehaftete
16-bit-Zahl.  Damit geht testVar[16384] als maximale Größe.
Andererseits sollte deine gewünschte 128*123-Dimension da noch
hereinpassen.

malloc() müsste auch größere Blöcke ausfassen können, aber ich habe
die Befürchtung, dass die Indexrechnererei des Compilers dir dennoch
in die Suppe spucken könnte.  Andererseits hast du, wenn ich deine
extmem-Einstellungen richtig deute, ja sowieso nur 32 KiB externen
Speicher dran, damit sollte das ja genügen.

von Timo Birnschein (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jörg,

ja, ich habe mir schon gedacht, dass du wohl an Weihnachten was anderes
zu tun hast :)

Noch ein Versuch mit einer kleinen Frage vorweg: An welcher Stelle hast
du die Kompatibilität zu 1.2 im Makefile angegeben? Ich kann das leider
nicht finden, nachdem ich alles durchgeschaut habe. Allerdings geht bei
mir die fdevopen Routine. Mit einer kleinen Warnung, aber sie läuft.

Zum Thema: Ich habe heute das "How to use external RAM?" der AVR-libc
Homepage durchgelesen und die entsprechende Assemblerdatei geschrieben
und eingelinkt. Das läuft auch durch und sieht folgendermaßen aus:

;; begin xram.S

#include <avr/io.h>

        .section .init1,"ax",@progbits

        ldi r16,_BV(SRE)
        out _SFR_IO_ADDR(MCUCR),r16
    //ldi r16, _BV(XMBK) | _BV(XMM0)
    //out _SFR_IO_ADDR(XMCRB),r16
    // warum das nicht geht, entzieht sich meiner Kenntnis...

;; end xram.S

Um gleich an dieser Stelle zu definieren, dass ich nur 32KB SRAM
angebunden habe, wollte ich das Register XMCRB entsprechend schon hier
setzen. Leider bekam ich eine Fehlermeldung, mit der ich als
Assembler-Laie nicht viel anfangen kann, weswegen die entsprechenden
zwei Zeilen auskommentiert sind.

xram.S: Assembler messages:
xram.S:10: Error: number must be less than 64

Außerdem habe ich mit mfile ein neues Makefile erstellt, was jetzt den
Anforderungen entsprechen sollte. Also SRAM-Größe, Adressraum ect. Um
auch den Bug aus zu schließen, den du angesprochen hast, habe ich das
Makefile nochmal mit deiner geänderten Zeile modifiziert.

Auch weiterhin weigert sich mein Programm Arrays deutlich größer als
testVar[1024] an zu sprechen. Wenn ich z.B. testVar[2048] probiere,
startet der code laufend neu.

Meine Hoffnung ist, dass es nurnoch einer Änderung im Assemblerfile
bedarf, die entsprechend dem Compiler klar macht, dass es nur 32 KB und
nicht 64KB sind.

Sorry, dass ich so viel dazu schreibe, aber der Fehler ist, wenn man es
nicht auf einem Prozessor testen kann, sehr komplex zu beschreiben! Der
Code compiliert ja einwandfrei, nur die Ausführung haakt gewaltig.

Kennst du evtl ein gutes Beispiel, wo ich mir das nochmal Schritt für
Schritt abschauen kann? Ich konnte selbst nach langem suchen kein
wirklich anschauliches Beispiel finden.


Vielen Dank nochmal!

Timo

ps. ich habe nochmal den aktuellen Code mit angehängt.

von Fritz G. (fritzg)


Lesenswert?

Ich hab auf einem Mega64 extern 32kB RAM, das einzige was ich gemacht
habe war im Makefile:

EXTMEMOPTS =
-Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x8090ff

und bei Programstart:
    MCUCR = _BV (SRE) | _BV (SRW10);    // externes RAM enablen, 1
Waitstate
    XMCRB = _BV (XMM0);

allerdings mit der Einschränkung dass normale Variablen ins interne
SRAM kommen, und nur der Speicher, der über malloc() angefordert wird,
im externen SRAM liegt. Geht ohne Probleme.

von Timo Birnschein (Gast)


Lesenswert?

Vielen Dank! Jetzt weiß ich, dass das wirklich geht.

Das komische ist nämlich, dass mein Prozzi sich "normal" verhällt,
wenn ich nur den heap in den Ext.SRAM lege. Das habe ich mal versucht.
Mir war allerdings der Weg über Malloc() bislang zu komplex, weil ich
damit noch nie gearbeitet habe.

Du brauchtest auch keine Assemblerdatei zu schreiben, eben weil der
Compiler eh keine Laufvariablen automatisch in das Ext.SRAM schmeißt.
Es ist also der einfachere Weg, aber offenbar auch der bessere.

Ich werde das heute nachmittag testen!

Kannst du mir evtl noch posten, wie du mit Malloc() Speicher
reservierst? Ich habe mir das gestern angeschaut, bin allerdings aus
dem Void-Pointer nicht so richtig schlau geworden :(

von Fritz G. (fritzg)


Lesenswert?

uint16_t *feld; // Zeiger auf Integer

// 1000 Zahlen
feld=malloc(2000);
oder besser:
feld=malloc(1000*sizeof(uint16_t);

*feld=1; // 1 in den ersten Speicherort

*(feld+10)=5; // Zahl in die 10. Speicherstelle, aber 20. Byte!

von Timo Birnschein (Gast)


Lesenswert?

Ja, genau das beispiel habe ich gesucht :)

Damit wird es sicher gehen!

Vielen Dank für deine Hilfe!

von Timo Birnschein (Gast)


Lesenswert?

Guess what? Es geht!

Nach Wochen des Suchens und der Undurchsicht endlich die Lösung!

Vielen Dank nochmals!

Timo

von Fritz G. (fritzg)


Lesenswert?

Achja, richtig wärs natürlich immer so zu schreiben:

feld=malloc(1000*sizeof(uint16_t));
if (feld==NULL)
  printf("Scheisse");

Grad bei MCs hat man nicht unbegrenzt 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.