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:
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?
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.
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=802200
das scheint nicht mit Ihrem Wunsch auf der Kommandozeile übereinzustimmen . Sie können den Pfad von __DATA_REGION_ORIGIN__
bis .data
im .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 ld
Wert ü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 ld
Prozess 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 -v
zum ld-Befehl kann weitere Informationen liefern, die zeigen, was wirklich vor sich geht ...
user_1818839
Peter W
Oli
Oli
user_1818839
__DATA_REGION_ORIGIN__ = DEFINED(__DATA_REGION_ORIGIN__) ? __DATA_REGION_ORIGIN__ : 0x800200;
.data=802200
scheint auf der Kommandozeile nicht zu stimmen . Vielleicht müssen Sie__DATA_REGION_ORIGIN__
die Linker-Argumente einstellen?Oli
Lundin
Oli
HaLaila HaZeh
__attribute__ ((section (".init3"))