Verschieben von Daten, Bss und Heap-Speicher auf externes SRAM Atmega2560

Dies ist meine erste Frage hier, entschuldigen Sie, wenn ich etwas übersehe.

Ich verwende einen Atmega2560 als Hauptprozessor für mein Projekt, aber mir geht der Arbeitsspeicher aus, also habe ich einen externen 64 KB (64 x 8) SRAM daran angeschlossen. Ich habe mich umgesehen und einige Projekte und Bibliotheken gefunden, die den externen SRAM verwenden:

http://andybrown.me.uk/wk/2011/08/28/512kb-sram-expansion-for-the-arduino-mega-design/

https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield

Aber alle verwenden das externe SRAM als Heap-Speicher.

Ich möchte den externen Speicher als Daten-, BSS- und Heap-Speicher verwenden und den gesamten SRAM für den Stapel belassen.

Ich habe dies im avr-libc-Handbuch gefunden: https://www.nongnu.org/avr-libc/user-manual/malloc.html

Anhand der Informationen aus dem Handbuch habe ich das Makefile für den Arduino Mega Bootloader hier geändert: C:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders\stk500v2

Link zum ursprünglichen Makefile: https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/stk500v2/Makefile

Ich habe „EXTMEMOPTS =“ wie folgt geändert:

EXTMEMOPTS = -Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x80ffff

0x800000 ist der Offset für die Harvard-Architektur, 0x802200 ist die erste Adresse für den externen Speicher.

Ich kompiliere den Bootloader mit der neuen Make-Datei neu, erhalte jedoch die folgende Fehlermeldung:

Geben Sie hier die Bildbeschreibung ein

Ich glaube, es beschwert sich, weil die Adresse außerhalb des internen SRAM liegt. Ich konnte keine Möglichkeit finden, das Problem zu beheben.

Ich bin mir nicht sicher, was falsch ist, was übersehe ich? Auch wenn dies gelöst wird, ist es in Ordnung, die externe Speicherhardware (durch Setzen der XMCRA- und XMCRB-Register) in der Hauptfunktion des Bootloaders zu initialisieren? Wenn nicht wo soll ich das machen?

Update: Hier ist das Linker-Skript: https://codeshare.io/aJom3K

Update 2: Das erste Problem ist jetzt gelöst; Ich habe die falsche ld-Datei bearbeitet und nachdem ich die richtige Datei in die folgende geändert hatte, funktionierte es:

DATA_REGION_ORIGIN = 0x802200;

Das nächste Problem ist, wo man die Hardware für externes SRAM initialisiert? Ich mache das derzeit in der __jumpMain- Funktion des Bootloaders, die auch das Stack-Pointer-Register setzt. Ist das in Ordnung oder sollte ich das woanders machen?

Bootloader: https://codeshare.io/5zNr1b

Update 3: Wie von @Brian Drummond in der Teilantwort erwähnt, habe ich die Linker-Argumente wie folgt geändert:

EXTMEMOPTS = -Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x80ffff,--defsym= DATA_REGION_ORIGIN =0x802200

und die Änderungen am Build-Skript zurückgesetzt, um Probleme in der Zukunft zu vermeiden.

Für alle, die etwas Ähnliches tun: Sie müssen auch Argumente hinzufügen, um die DATA_REGION_LENGTH auf die neue Länge zu ändern. Andernfalls wird nur die alte Länge verwendet, die in meinem Fall lautet: 0xfe00.

Update 4: Nach einigen Tests verwendet der MC anscheinend nicht das externe SRAM; Nachdem ich es mit dem neuen Skript programmiert habe, kann ich das SRAM trennen und es wird weiterhin gut funktionieren. Ich habe auch die Daten- und Adressleitungen zum SRAM überprüft und es wird nichts geschrieben oder gelesen.

Also bin ich wieder am Anfang, Irgendwelche Ideen, was falsch ist?

Wie sieht die .ld-Datei aus?
Ich hasse es, es zu sagen, aber wenn Ihre Firmware dynamische Zuweisung und externen SRAM benötigt, ist der AtMega möglicherweise nicht der richtige Chip für den Job
Hier ist die Linker-Skriptdatei: codeshare.io/aJom3K
@PeteW Ich weiß, dass ich es forciere und ich werde in Zukunft zum Arm wechseln, aber ich möchte dieses Problem zuerst lösen.
__DATA_REGION_ORIGIN__ = DEFINED(__DATA_REGION_ORIGIN__) ? __DATA_REGION_ORIGIN__ : 0x800200;.data=802200scheint auf der Kommandozeile nicht zu stimmen . Vielleicht müssen Sie __DATA_REGION_ORIGIN__die Linker-Argumente einstellen?
@BrianDrummond Vielen Dank, ich habe die ganze Zeit die falsche ld-Datei geändert. Nachdem du es erwähnt hast, wurde es mir klar. Ich habe die Bedingung entfernt und die ld-Datei wie folgt geändert: DATA_REGION_ORIGIN = 0x802200; und es löste das Problem. Aber ich bin mir nicht sicher, wo es ursprünglich definiert wurde, denn wenn ich die Bedingung dort sein lasse, erhalte ich den gleichen Fehler.
Warum haben Sie einen Haufen auf einem 8-Bitter und warum können Sie ihn nicht einfach löschen, um Speicher freizugeben? Es sitzt einfach in Ihrem RAM und nimmt ohne guten Grund Platz ein.
@Lundin Der Heap ist mir egal und er wird nicht verwendet, die obigen Linker-Argumente sind nur ein Test. Mein Hauptziel war es, die .data und .bss in den externen SRAM zu verschieben.
Versuchen Sie vielleicht, XMCRA im init3-Abschnitt mit zu initialisieren__attribute__ ((section (".init3"))

Antworten (2)

TL;DR Dies wird nicht so funktionieren, wie Sie es möchten, da der Atmega2560 keine externe Speicherschnittstelle hat.

Wenn Sie eine Variable erstellen, die im [internen] SRAM gespeichert wird, kann die ALU des Prozessors diese Variable abrufen, da die ALU und das SRAM mit demselben internen Speicherbus verbunden sind. Bei High-End-Prozessoren (z. B. STM32F756) haben Sie manchmal ein dediziertes Peripheriegerät mit externer Speicherschnittstelle, das beispielsweise eine Verbindung zu SRAMs, DRAMs, SDRAMs usw. herstellen kann. Diese Peripheriegeräte sind etwas Besonderes, da sie das interne Speicherbusprotokoll konvertieren des Prozessors in die externe Hardwareschnittstelle, die zum Laden/Speichern von Daten auf einem externen Speicherchip benötigt wird.

Eine einfache [r] Analogie ist diese: Ihr ATmega2560 hat ein SPI-Peripheriegerät. Wenn Sie das als SPI-Master konfigurieren und etwas in das SPI-Datenregister schreiben, taktet das Peripheriegerät die Bits automatisch ohne weiteren CPU-Eingriff auf den Bus. Sie haben einen Speicherzugriff (das Schreiben von Datenregistern) in ein physikalisches Protokoll übersetzt.

Umgekehrt könnten Sie Code schreiben, der die IO-Pins manuell wackelt, um das gleiche Hardwareergebnis wie das SPI-Peripheriegerät zu erzielen. Dies hat eine Reihe von Einschränkungen, die wichtigste besteht darin, dass Sie ein Datenbyte manuell entpacken und die Pins zu den entsprechenden Zeiten manuell (per Code) setzen müssen. Es sollte offensichtlich sein, dass dieser Code unter der Haube viele Lese- und Schreibvorgänge im Speicher durchführt und Sie nicht mehr die automatische Konvertierung von "In Datenregister schreiben, Bits austakten" wie bei dem dedizierten SPI-Peripheriegerät haben.

Was Sie mit Ihrem externen SRAM und Linker-Skript zu implementieren versuchen, wird nicht funktionieren, da dieser Adressraum für den Mikrocontroller und den Linker einfach nicht existiert und es kein Hardware-Peripheriegerät gibt, das Busanweisungen konvertieren kann in externe Speichersignale. Die Projekte, die Sie verknüpft haben, verwenden einfach eine Softwareschicht, um die IO-Pins manuell zu steuern, um mit dem externen SRAM zu kommunizieren (auch bekannt als Bit-Banging).

Bearbeiten zum Hinzufügen: Sie können immer noch ein externes SRAM verwenden, es wird nur nicht automatisch sein. Sie benötigen eine Softwarebibliothek, damit es funktioniert, und Sie müssen Daten explizit über eine Art API speichern/laden. Wenn Ihnen der SRAM ausgeht und Ihr Programm nicht gelinkt werden kann, dann haben Sie Pech gehabt. Es gibt einige extrem hackige Wege, dies zu umgehen, aber ich empfehle sie nicht. Verringern Sie stattdessen entweder die Speicheranforderungen Ihrer Anwendung, bis sie verknüpft werden kann, oder wechseln Sie zu einem leistungsfähigeren Mikrocontroller. Ich würde letzteres empfehlen und sagen, dass Sie den externen Speicher loswerden, denn selbst bei einem Prozessor mit einer externen Speicherschnittstelle ist das Hinzufügen von externem Speicher ein ernsthafter Kosten-, Komplexitäts- und Zeitfaktor.

Danke für die Klarstellung, ich war verwirrt von dem Datenblatt, das die XMEM-Schnittstelle (External Memory Interface) aufnimmt und wie es alles automatisch handhabt, auch die AVR-LIBC-Dokumentation ließ es so aussehen, als wäre dies möglich; Das System, an dem ich arbeite, ist nur ein Prototyp und ich werde es auf ein ARM upgraden, da es, wie Sie bereits erwähnt haben, viel effizienter und einfacher ist.

Teilantwort:

Wenn wir uns die .ld-Datei (Linker-Skript) ansehen, können wir sehen

__DATA_REGION_ORIGIN__ = DEFINED(__DATA_REGION_ORIGIN__) ? __DATA_REGION_ORIGIN__ : 0x800200;

.data=802200das scheint nicht mit Ihrem Wunsch auf der Kommandozeile übereinzustimmen . Sie können den Pfad von __DATA_REGION_ORIGIN__bis .dataim .ld-Skript selbst nachverfolgen.

__DATA_REGION_ORIGIN__Was darauf hindeutet, dass Sie die Linker-Argumente (in der Befehlszeile) festlegen können und (falls festgelegt) den im .ld-Skript angegebenen ldWert überschreiben .0x800200

Oder bearbeiten Sie den Ausdruck im Linker-Skript. Das einfache Bearbeiten des Werts sollte (nach meinem Verständnis) funktionieren, aber anscheinend liefert etwas anderes (aber WAS?) Im ldProzess einen Wert, der den Skriptwert überschreibt. Ich finde, dass der .ld-Prozess unnötig undurchsichtig ist, und ich behaupte nicht, ihn vollständig zu verstehen.

Als Problemumgehung können Sie den bedingten Ausdruck löschen und nur den Wert übrig lassen, aber Sie müssen mit "inoffiziellen" Änderungen zum Erstellen von Skripten vorsichtig sein, da sie später zu Wartungsproblemen führen.

Das Hinzufügen -vzum ld-Befehl kann weitere Informationen liefern, die zeigen, was wirklich vor sich geht ...

Diese Antwort verfehlt den Punkt, dass der ATMega2560 keine Möglichkeit hat, externe SRAMs zu speicherzuordnen, und keine Menge Linker-Skript-Fummelei wird dies beheben. Wenn überhaupt, wird das nur die Verknüpfung unterbrechen und nichts wird funktionieren.