Forum: Mikrocontroller und Digitale Elektronik Frage zu Externes SRAM(XMEM) und Atmel Studio 7


von Felix N. (felix_n888)


Lesenswert?

Guten Abend liebe Community,

Ich habe vor kurzen eine neue Platine anfertigen lassen um mein 
bestehendes Projekt auszuweiten wechsele ich vom ATMega1284P auf den 
ATMega2560. Der ATMega2560 ist auch auf der neuen Platine verbaut.

Da der ATMega2560 nur über 8K SRAM anstatt wie sein kleiner Bruder über 
16K und ich jetzt bei knapp 6,3 kB SRAM verbrauch bin. Habe ich ein 
Externen SRAM auf der Platine mit verbaut.

Der SRAM ist vom Hersteller ISSI und trägt die Bezeichnung 
IS61C5128AL-10TL, hab damals von irgendwelchen Geräten 3 Stück von den 
ausgelötet. Der SRAM ist natürlich absoluter Overkill mit seinen 4Mb 
(512kB) und ich kann ihn auch nicht voll adressieren da AVRs ja nur max. 
64kB direkt können. Habe die überschüssigen Adresspins A16 bis A18 auf 
normale I/O Pins des Mikrocontrollers gelegt.

Könnte in der Theorie glaubig Bank Switching machen und so denn gesamten 
Adressraum des SRAM bekommen aber erstmal nicht und ich weiß auch nicht 
ob der AVR so programmierbar ist das er von sich aus dieses Bank 
Switching macht, glaube ja nicht.

Im Datenblatt zum Prozessor steht ja unter "External Memory Interface" 
für das Register XMCRB die XMM Bits um Pins freizugeben. Ich habe dort 
keins dieser XMMn Bits gesetzt so das ich alle Address High Pins nutze. 
Jetzt steht in Klammern als vermerk dort "(Full 56Kbytes space)" 
desweitern steht dort mit drin weiter oben "Using all 64Kbytes Locations 
of External Memory" das man diese bekommt wenn man alle Pins an PortC 
freigibt für den XMEM Bus. Aber das habe ich dort getan wenn ich keins 
der XMMn Bits setzte oder? Also kann ich doch jetzt die vollen 64kB 
ansteuern oder nicht? Im Linker habe ich eingestellt das die .data 
Sektion bei 0x802200 beginnt, also nach dem internen SRAM.

Nix desto trotz habe ich den SRAM schon mal getestet. Denn Linker habe 
ich so konfiguriert das die .data und .bss sowie der Heap im Externen 
RAM liegen und der Stack im interen. Als erstes habe ich mal 50.000 
bytes mit malloc belegt mit Werten zuweisen und wieder ausgelesen dieses 
funktionierte ohne Fehler. Danach wollte ich das ganze nochmal mit 
normalen Variablen testen da ich nicht so viel gebrauch von malloc 
mache. Also habe ich 3 uint16_t Arrays jeweils mit einer Größe von 4000 
anlegt. Auch wieder werte zugeweisen und ausgelesen tat alles wenn ich 
zwischen zwei Arrays mal eins der anderen Highbits(A16-A18) auf HIGH 
sitze kommt für das Array nur Müll raus. Ist ja klar die Adresse stimmt 
dann ja nicht mehr. Also der SRAM tut schon mal so wie er soll.

Nur bekomme ich beim Kompilieren ein Speicherüberlauf in meinen Fall 300 
%. 25kB benutzt von 8kB. In Atmel Studio gibt es ja unter "Project -> 
Properties" unter "Toolchain -> General" die Möglichkeit ein Externen 
RAM Check einzuschalten(External ram check for memory overflow (only if 
device supports this)).

Aber wenn ich danach nochmal kompiliere(External Ram Check 
eingeschaltet) bekomme ich immer noch den gleichen Fehler. Nur wenn ich 
in der Compilier Datei im Ordner "Vs" den Punkt 
"RunOutputFileVerifyTask" rauslösche klappt es Problemlos da dieser Task 
ja gar nicht mehr ausgeführt wird. Aber genau dafür gibt es doch diese 
Option im AS7 oder nicht? Muss man da noch etwas einschalten oder 
eintragen damit es funktioniert?

Mfg

von Falk B. (falk)


Lesenswert?

> Könnte in der Theorie glaubig Bank Switching machen und so denn gesamten
> Adressraum des SRAM bekommen

Ja, kann man.

> aber erstmal nicht und ich weiß auch nicht
> ob der AVR so programmierbar ist das er von sich aus dieses Bank
> Switching macht, glaube ja nicht.

Nö, geht nicht, ist "Handarbeit".

> Im Datenblatt zum Prozessor steht ja unter "External Memory Interface"
> für das Register XMCRB die XMM Bits um Pins freizugeben. Ich habe dort
> keins dieser XMMn Bits gesetzt so das ich alle Address High Pins nutze.
> Jetzt steht in Klammern als vermerk dort "(Full 56Kbytes space)"
> desweitern steht dort mit drin weiter oben "Using all 64Kbytes Locations
> of External Memory" das man diese bekommt wenn man alle Pins an PortC
> freigibt für den XMEM Bus. Aber das habe ich dort getan wenn ich keins
> der XMMn Bits setzte oder? Also kann ich doch jetzt die vollen 64kB
> ansteuern oder nicht?

Nicht ganz, denn der externe SRAM teilt sich den Adressraum mit dem 
internen SRAM und den IO-Registern.

> Im Linker habe ich eingestellt das die .data
> Sektion bei 0x802200 beginnt, also nach dem internen SRAM.

Kann man machen.

https://scienceprog.com/adding-external-memory-to-atmega128/#more-2513
http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
www.nongnu.org/avr-libc/user-manual/malloc.html

von c-hater (Gast)


Lesenswert?

Felix N. schrieb:

> Könnte in der Theorie glaubig Bank Switching machen und so denn gesamten
> Adressraum des SRAM bekommen

Um den gesamten externen RAM nutzen zu können, musst du auf jeden Fall 
Bank-Switching betreiben. Ohne Bank-Switching kannst du maximal knapp 
56kByte davon benutzen.

> Im Datenblatt zum Prozessor steht ja unter "External Memory Interface"
> für das Register XMCRB die XMM Bits um Pins freizugeben. Ich habe dort
> keins dieser XMMn Bits gesetzt so das ich alle Address High Pins nutze.
> Jetzt steht in Klammern als vermerk dort "(Full 56Kbytes space)"

Genau. Der Adressbereich von 0..0x21ff bleibt dem internen "Speicher" 
(also nicht nur RAM, sondern auch Registerfile und MMIO) zugeordnet. Von 
der aktuell ausgewählten 64k-Bank des externen RAM kannst du deshalb auf 
eben jenen Bereich nicht zugreifen.

Die übliche Lösung ist, PC7 nicht in das XMEM-Interface einzubeziehen, 
sondern ebenfalls zum Bank-Switching zu benutzen. Der Vorteil ist, dass 
man Zugriff auf den gesamten externen RAM bekommt, der Nachteil ist, 
dass eine Bank halt nur noch 32kB groß ist.

Muss man halt abwägen, was einem für die Anwendung wichtiger ist, ein 
möglichst großes Stück "Speicher am Stück" oder möglichst viel Speicher.

von Felix N. (felix_n888)


Lesenswert?

Falk B. schrieb:
> Nö, geht nicht, ist "Handarbeit".

Hallo Falk.

Ah ja habe ich mir schon irgendwie gedacht.

Falk B. schrieb:
> Nicht ganz, denn der externe SRAM teilt sich den Adressraum mit dem
> internen SRAM und den IO-Registern.

Ja das ist mir bekannt. Im Datenblatt findet sich ja Figure 9-1 "Memory 
Configuration A" dort steht ja drin das alles von 0x0000 bis 0x21FF zum 
Internen Speicher gehörten. Meine auch im Datenblatt gelesen zu haben 
was genau alles dazu gehört. Der eigentliche RAM startet glaubig bei 
0x1000 dazwischen müssten die I/O Registers sein.

Aber das ist doch für mich eigentlich egal oder? Denn schließlich darf 
ich ja erst ab 0x2200 arbeiten bis maximal 0xFFFF. Dann habe ich ja für 
das Externe RAM 56.831 mögliche Adressen bzw. 56kB an Speicher das ist 
klar.

c-hater schrieb:
> Die übliche Lösung ist, PC7 nicht in das XMEM-Interface einzubeziehen,
> sondern ebenfalls zum Bank-Switching zu benutzen. Der Vorteil ist, dass
> man Zugriff auf den gesamten externen RAM bekommt, der Nachteil ist,
> dass eine Bank halt nur noch 32kB groß ist.

Ach so. Ja aber wenn ich doch die XMMn Bits setzte und somit PC7 
freigebe. Wer schaltet das denn dann letztendlich wieder um? Ich oder 
die Compiler selbst wenn er es für nötig hält?

Falk B. schrieb:
> Kann man machen.

Ja die Seiten kenne ich schon und habe mich zum großen Teil dort schon 
reingelesen.

So wie ich das jetzt verstanden habe gibt es zwei "Hauptmöglichkeiten" 
ein Externen SRAM zu verwenden. Option 1 ist das man die .data und .bss 
sowie den Heap der von malloc benutzt wird in den Externen RAM auslagert 
oder Option 2 das man nur den Heap auslagert in den Externen RAM aber 
die .data und .bss Daten im Internen RAM lässt genau so wie den Stack, 
wobei der Stack wohl immer im Internen RAM bleiben soll habe ich mal 
gelesen.

Ich habe meinem Linker jetzt folgende Anweisung gegebenen:
1
-Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x80ffff

Also .data und .bss sowie Heap in den Externen RAM. Anderes macht es für 
mich kein wirklichen Sinn nur den Heap auszulagern da ich malloc so gut 
wie nie benutzte, und der Heap wird glaubig zum großen Teil nur von 
malloc verwendet.

Desweitern initialisiere ich direkt nach den includes in der main den 
xram mit dem verweis auf .init3 so dass der Externe RAM vor den 
initialisieren von .init4 und somit den Kopieren der Daten in den RAM 
bereits vorhanden ist.
1
... F_CPU define und includes etc...
2
3
//External Memory needs to be available before Data is copied to the RAM (.init4)
4
void xram (void) __attribute__ ((naked)) __attribute__ ((section (".init3")));
5
void xram(void) {
6
  XMCRA = 0;          //Reset XMEM
7
  XMCRA |= (1<<SRE);  //Enable XMEM, No Wait Time, No Sector Limit
8
  XMCRB = 0;          //No Released Port Pins. Full 56kB Space
9
}
10
11
... Variables, Subroutinen, main(void) etc...

c-hater schrieb:
> Muss man halt abwägen, was einem für die Anwendung wichtiger ist, ein
> möglichst großes Stück "Speicher am Stück" oder möglichst viel Speicher.

c-hater schrieb:
> Um den gesamten externen RAM nutzen zu können, musst du auf jeden Fall
> Bank-Switching betreiben. Ohne Bank-Switching kannst du maximal knapp
> 56kByte davon benutzen.

Ja wie gesagt der RAM ist eh absoluter Overkill für das System ein 62256 
hätte eigentlich auch locker gereicht, nur hatte ich diese hier noch 
rumfliegen daher hatte ich diesen genommen. In meinen Fall würde ich mir 
für das größere Stück Kuchen entscheiden anstatt mehrere Stücke, ich 
werde eh niemals, glaubig ich zu mindestens bis jetzt, die vollen 56kB 
SRAM voll bekommen.

Das ganze ist für mein Aquarium Steuergerät. Hatte ja schonmal ein Thead 
wo es bei mir um den Programmspeicher ging. Durch neu schreiben des 
Codes und optimieren konnte ich nochmal einiges an Speicher freigeben so 
das die 128K vom 1284P eig. nicht voll waren, wahr irgendwo jetzt bei 
85kB oder so. Nur sind mir die Pins ausgegangen bei dem 40-Pinningen 
PDIP Prozessor. Daher jetzt der Wechsel auf den größeren Bruder nur mit 
8K SRAM wäre ich ganz sicher nicht ausgekommen.

Habt ihr eventuell auch Ahnung von Atmel Studio was das sein könnte? 
Kompilieren scheint trotzdem zu funktionieren. Bzw. geänderte Sachen im 
Code sind nachdem Hochladen auch vorhanden trotz Memory Overflow Fehler 
macht aber kein Unterschied ob ich "External Memory Check" an habe oder 
nicht.

Mfg

von Falk B. (falk)


Lesenswert?

Felix N. schrieb:

> So wie ich das jetzt verstanden habe gibt es zwei "Hauptmöglichkeiten"
> ein Externen SRAM zu verwenden. Option 1 ist das man die .data und .bss
> sowie den Heap der von malloc benutzt wird in den Externen RAM auslagert
> oder Option 2 das man nur den Heap auslagert in den Externen RAM aber
> die .data und .bss Daten im Internen RAM lässt genau so wie den Stack,
> wobei der Stack wohl immer im Internen RAM bleiben soll habe ich mal
> gelesen.

Ja.

> Also .data und .bss sowie Heap in den Externen RAM. Anderes macht es für
> mich kein wirklichen Sinn nur den Heap auszulagern da ich malloc so gut
> wie nie benutzte, und der Heap wird glaubig zum großen Teil nur von
> malloc verwendet.

Ja.

> Das ganze ist für mein Aquarium Steuergerät.

Und dafür reichen 8kB SRAM nicht aus? Was machst du damit? Mit 8kB sind 
die Amis der Legende nach auf dem Mond gelandet.

von au weia (Gast)


Lesenswert?

Falk B. schrieb:
> Und dafür reichen 8kB SRAM nicht aus? Was machst du damit?

Vielleicht ist noch nicht bis zu jedem AVR-User vorgedrungen
dass man mit Strings nur im Flash eine Menge RAM sparen kann.

Und plötzlich passt der ganze Code sogar in den kleinen 328P!

von Felix N. (felix_n888)


Lesenswert?

Falk B. schrieb:
> Ja.

Falk B. schrieb:
> Ja.

Alles klar! Danke

Falk B. schrieb:
> Und dafür reichen 8kB SRAM nicht aus? Was machst du damit? Mit 8kB sind
> die Amis der Legende nach auf dem Mond gelandet.

Naja wenn man sich mal wie größten Fresser anschaut ENC28J60, ILI9341 
Display und SD-Karte und halt die Variablen. Vor der Optimierung war der 
RAM Verbrauch deutlich höher so um die 12 bis 13kB meine ich. Ein sehr 
sehr großer Teil ist durch das verwenden von PROGMEM bzw. allgemein der 
pgmspace.h frei geworden indem ich die Strings nur im Flash habe. Und 
die GUI zum Bedienen wird mit Sicherheit auch ein bisschen RAM belegen. 
Bin im Moment bei 6450 Bytes, hab gerade mal geschaut.

Alleine bei dem ENC28J60 nutze ich halt den WWW-Server sowie den 
NTP-Client wenn ich das beides deaktivieren würde bekam ich schon wieder 
ein Stück frei aber die beiden Funktionen brauche ich.

au weia schrieb:
> Vielleicht ist noch nicht bis zu jedem AVR-User vorgedrungen
> dass man mit Strings nur im Flash eine Menge RAM sparen kann.
>
> Und plötzlich passt der ganze Code sogar in den kleinen 328P!

Weiß ich, bei mir gibt es mittlerweile fast keine Strings mehr die im 
RAM so direkt liegen sofern sie nicht zu Debugging Zwecken dienen, dann 
lasse ich sie für die Fehlersuche oder what ever im RAM liegen da sie eh 
daraus später wieder gelöscht werden.

Lg

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.