Hallo,
ich habe einem Arduino Mega2560 32k externes RAM gegönnt und versuche
das jetzt möglichst flexibel einzurichten.
Die Methode die auf
https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield
erwähnt wird, lässt ja nur zu dynamische Variablen in den XRAM zu
schieben.
Laut https://www.nongnu.org/avr-libc/user-manual/malloc.html kann man
auch .data und .bss in den externen Speicher schieben, aber das
funktioniert nicht :/
Ich habe mir in der Arduino-Umgebung ein eigenes board erstellt.
Dazu reicht es im sketch-folder einen Ordner mit einer boards.txt
anzulegen.
Um die Linker flags übergeben zu können braucht es dann noch eine
platforms.txt mit dem Eintrag
leider klappt das nicht - ich habe es nicht weiter untersucht, aber an
der seriellen kommt keine Ausgabe
Wenn ich jedoch nur den heap in den externen RAM verweise
dann funktionniert das wunderbar.
Allerdings habe ich dann wieder die Einschränkung dass nur dynamisch
erstellte Variablen dahin verwiesen werden.
Leider ist mein Verständnis von Compiler und Linker recht gering und ich
weiss nicht wie ich hier weitersuchen soll, bzw. was da überhaupt
passiert.
Bin für jeden Hinweis dankbar!
Bob A. schrieb:> Die Methode die auf> https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield> erwähnt wird
Nachdem ich eine zeitlang bei den hackadays gesucht habe und
dort nichts gefunden habe erlaube ich mir dir die Frage zu stellen
ob du jemals den Begriff "Abblock-Kondensator" gehört hast.
Klar, ich weiss, das ist reine Esoterik, Abblock-Kondensatoren
sind rein für die Ästhetik und zeugen davon dass der geneigte
Arduino-Besitzer genug Geld hat um seine Werke zu verschönern.
Ansonsten machen die Kondensatoren ja keinen Sinn, ausser
Beschäftigungstherapie.
Aber ich frag halt mal ..... ich weiss, das macht dein Speicher-
Problem nicht besser ....
Ich schrub doch: "bin für jeden Hinweis dankbar" :)
also Danke dafür!
Habe das im Eifer und in der Freude dass der Drahtverhau tatsächlich
funzt grad mal vergessen.
Wird nachgerüstet und kommt auch ganz sicher ins fertige Layout.
Und ja, leider hilfts bei der eigentlichen Fragestellung nicht weiter...
auch wenns womöglich später die Suche nach dem Ursprung von obskurem,
sporadischen Fehlverhalten unnötig macht :)
Ob der Abblock-C bei all den schönen Antennen aber das größte Problem
ist...
Bob A. schrieb:> Ob der Abblock-C bei all den schönen Antennen aber das größte Problem> ist...
Nicht der_ sondern _die! Für jeden Baustein einen und für die
Board-zu-Board-Verbindung noch einen Elko 10-47uF.
Du fällst aus der Rolle der Arduino-Maker! Du meinst wirklich
man könnte Kondensatoren vorsichtshalber einbauen? Ich kenne
nur die Betonköpfe die sagen es geht auch ohne.
Selbst hackadays turnt dir vor dass es keine Abblock-
Kondensatoren braucht!
ich hab mir jetzt mal das .elf angeschaut mit dem netten online viewer
von Bastian Molkenthin
(http://www.sunshine2k.de/coding/javascript/onlineelfviewer/onlineelfviewer.html)
Nur schade dass ich nicht so ganz kapiere was ich da sehe...
Mir scheint dass es in dem Bereich "Program Header Table" sich die
Addressen für .data und .bss wiederfinden. Und zwar unterteilt in
virtuelle und physische Addressen.
im XMEM: (Einträge eingekürzt damit es keinen Zeilenumbruch gibt)
1
Programheadertables
2
=====================
3
4
TypeOffsetVAddrPAddr
5
PT_LOAD0x000000940x000000000x00000000
6
PT_LOAD0x00000D940x008022000x00000D00
7
PT_LOAD0x00000E5E0x008022CA0x008022CA
Im section header sieht es dann so aus (auch gekürzt)
1
0SHT_NULL0x00000000
2
1.dataSHT_PROGBITS0x00802200
3
2.textSHT_PROGBITS0x00000000
4
3.bssSHT_NOBITS0x008022CA
Da oben die gleichen Addressen auftauchen und auch Offset und Size
passen gehe ich davon aus dass es sich auch bei den obigen Einträgen um
.data und .bss handelt.
im normalen Speicher (auch gekürzt)
1
Programheadertables
2
=====================
3
4
TypeOffsetVAddrPAddr
5
PT_LOAD0x000000940x000000000x00000000
6
PT_LOAD0x00000D940x008002000x00000D00
7
PT_LOAD0x00000E5E0x008002CA0x008002CA
Interessant finde ich, dass sich die Physiche Adresse von .data nicht
ändert, die von .bss aber sehr wohl.
Ob das was zu bedeuten hat - dafür reicht mein Wissensstand nicht.
Leider!
Weiterhin ist mir aufgefallen dass bei der XMEM-Variante für
DATA_REGION_ORIGIN (doppelte underscores vorn und hinten entfernt um
Formatierung zu verhindern) der Wert 0x0800200 erhalten bleibt,
__data_start
aber den Wert 0x0802200 zugewiesen bekommt.
Auch hier fehlt mir das nötige Wissen um das beurteilen zu können...
Würd mich freuen wenn jemand mich aufschlauen kann, bzw. mich in die
richtige Richtung weist wo man sich selber aufschlauen kann...
Bob A. schrieb:> leider klappt das nicht - ich habe es nicht weiter untersucht, aber an> der seriellen kommt keine Ausgabe
Das Problem wird sein, dass in XMCRA das SRE Bit gesetzt sein muss
bevor die Variablen (z.B. Serial) initialisiert werden.
Das kann man in einer frühen .init Section tun.
EAF schrieb:> Das kann man in einer frühen .init Section tun.
Hallo EAF,
auch wenn ich wenig Ahnung habe klingt das einleuchtend.
nur - wie kann ich das bewerkstelligen?
Hast du Doku zu den ganzen .init Sachen, evtl. Beispiele? Würde mich
gerne einlesen, weiss aber nicht wo anfangen
> Das kann man in einer frühen .init Section tun.
Das muss bereits im Startup-Code, der ja die Data-Sektion ins RAM
kopiert, drin sein.
Aber mal ehrlich: was soll der Krampf, die vermurksten 2560er noch mit
externem RAM zu erweitern - die werden dadurch nicht besser. Mehr als
64kB Kode+Daten wird mit 8-Bit-CPUs immer ein häßliches Gewurschtel - da
sollte man doch mal den Schritt zu 32-Bit-CPUs wagen. Ist ja nicht so,
dass die schwieriger zu kommen oder teurer sind ...
foobar schrieb:> Das muss bereits im Startup-Code, der ja die Data-Sektion ins RAM> kopiert, drin sein.
Danke sehr!
Ich versuche mal herauszufinden wie ich das bewerkstelligen kann
Bob A. schrieb:> Hallo EAF,>> auch wenn ich wenig Ahnung habe klingt das einleuchtend.> nur - wie kann ich das bewerkstelligen?> Hast du Doku zu den ganzen .init Sachen, evtl. Beispiele? Würde mich> gerne einlesen, weiss aber nicht wo anfangen
buffer 6 und 7 werden dynamisch erzeugt und korrekt irgendwo hinter
0x2200 und vor 0xA1FF geschoben
hier habe ich die Fkt. enableExternalMemory() wie oben beschrieben
eingefügt
Alles wie gehabt :(
Wie kann ich den startup-code modifizieren, und das dann auch noch so
dass es abhängig von der board-Auswahl in der Arduino IDE gemacht wird?
Ich habe den Test von
https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield
laufen lassen
Sagt: alles in Ordnung selbst mit 0 waitstate
Hast du da eine bessere Möglichkeit das zu testen?
Ja ich weiss, die Addressen sind total wirr. Keine Ahnung wie das
zustande kommt...
Eigentlich dürfte ja auch nix hinter 0xA1FF addressiert werden da das
als heap_end gefiniert wurde.
Zumindest soweit ich das verstanden habe...
foobar schrieb:> Mehr als> 64kB Kode+Daten wird mit 8-Bit-CPUs immer ein häßliches Gewurschtel - da> sollte man doch mal den Schritt zu 32-Bit-CPUs wagen. Ist ja nicht so,> dass die schwieriger zu kommen oder teurer sind ...
Genau, Arduino Due hat 96 KM SRAM direkt im uC. Kann genau wie gewohnt
mit der Arduino IDE programmiert werden. Warum sich mit den antiken
8-Bit-Controllern und ihrer schmalen Ausstattung rumplagen, während
längst wesentlich besser ausgestattete Controller Standard sind...
Oliver S. schrieb:> Ich sach mal, in Anbetracht der völlig wirren Adressen, die das tool> ausspuckt, vergiß das halt einfach.
Wieso wirr?
die wirren Adressen kommen nicht vom Tool sondern von "meinem"
Test-sketch
Programmierer schrieb:> Genau, Arduino Due hat 96 KM SRAM direkt im uC. Kann genau wie gewohnt> mit der Arduino IDE programmiert werden. Warum sich mit den antiken> 8-Bit-Controllern und ihrer schmalen Ausstattung rumplagen, während> längst wesentlich besser ausgestattete Controller Standard sind...
Das wäre ja einfach...
Mal davon abgesehen dass man mit dem arbeitet was man hat, habe ich
bisher schon Einiges lernen können.
Erkenntnisgewinn kann auch eine Motivation sein!
foobar schrieb:> Ehem, deine dataBuffer1-5 sind auf dem Stack!
Öhm... dann habe ich da wohl etwas grundlegend nicht verstanden.
Ich habe es so verstanden, dass Variablen die mit
Bob A. schrieb:> Da ändert sich leider genau nix wenn ich das Beispiel mit .init1> verwende
Das sich damit irgendwelche Adressen ändern, hätte ich auch nicht
erwartet.
Wie auch?
Bob A. schrieb:> Wie kann ich den startup-code modifizieren,
Das habe ich dir gezeigt!
.ini1 ist schon ein passender Zeitpunkt.
Bob A. schrieb:> und das dann auch noch so> dass es abhängig von der board-Auswahl in der Arduino IDE gemacht wird?
Arduino kennt Boards und Varianten.
Die kannst du selber erstellen und auch die vorhandenen modifizieren.
Hier finden sich die Regeln:
https://arduino.github.io/arduino-cli/0.20/platform-specification/
Bob A. schrieb:> Ich habe es so verstanden, dass Variablen die mit1int buffer[128]> (ich glaube man sagt dazu statisch) definiert werden kommen in die> .data-section
Wenn du das Zauberwort schon nennst, dann schreib das auch in den Code.
Dann klappt das auch mit .data
Oliver
Oliver S. schrieb:> Wenn du das Zauberwort schon nennst, dann schreib das auch in den Code.> Dann klappt das auch mit .data
ich habe das mal so interpretiert dass nur mit "static" deklarierte
Variablen in .data landen - richtig?
Das hat jetzt genau einmal funktioniert (array-Größe darf dann
allerdings nicht per Variable zugewiesen werden), alle Versuche das zu
wiederholen scheitern und es erscheint genau nix im Terminal... Da ist
doch zum Mäuse melken...
Bob A. schrieb:> Das hat jetzt genau einmal funktioniert
Was hat wie jetzt genau einmal funktioniert?
Zeig den Code, Compileraufruf, linkeraufruf, etc.
Und alles bitte als ANHANG.
Oliver
EAF schrieb:> Das sich damit irgendwelche Adressen ändern, hätte ich auch nicht> erwartet.> Wie auch?
Ich hatte das so verstanden, dass Variablen die so deklariert werden in
.data landen. Scheinbar ein Trugschluss
> Das habe ich dir gezeigt!> .ini1 ist schon ein passender Zeitpunkt.
Mir war nicht klar dass ich damit den startup-code ändere. Von den STM32
kenne ich das eher so, dass es eine separate Datei gibt in der der
startup-code enthalten ist. So einen Mechanismus wie hier, ich dachte
das ist was Anderes.
Wieder was gelernt ;)
> Arduino kennt Boards und Varianten.> Die kannst du selber erstellen und auch die vorhandenen modifizieren.> Hier finden sich die Regeln:> https://arduino.github.io/arduino-cli/0.20/platform-specification/
Soweit bin ich auch gekommen, ich habe im sketch-folder ein board
angelegt und die baords.txt so modifiziert dass es einen Atmega2560 mit
40k Speicher gibt und in der platform.txt die zusätzlichen Linker-Flags
hinterlegt.
Das klappt auch so weit.
Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten
der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen
wird.
EAF schrieb:> EAF schrieb:>> XMCRA |= 1ul<<7; // Switch ext mem iface on>> XMCRB = 0;> Das ist natürlich in meiner setup() Überflüssig, schadet aber auch> nicht.Oliver S. schrieb:> Was hat wie jetzt genau einmal funktioniert?
ich hatte die buffer als static und fest mit 1024 deklariert.
Runtergeladen und die buffer hatten andere Adressen.
Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.
Mal 'ne Minute von der Versorgungsspannung getrennt und es scheint
wieder wie gehabt zu funktioniern. fingerscrossed> Zeig den Code, Compileraufruf, linkeraufruf, etc.> Und alles bitte als ANHANG.
da ich nicht weiss was genau mit Compileraufruf gemeint ist (wird ja
öfter aufgerufen), mal der komplette output der Arduino-IDE.
Was genau möchtest du sehen und wie komme ich da ran?
Linker dürfte das hier sein:
Bob A. schrieb:> Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten> der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen> wird.
In dem du eine eigene variant erstellst.
Dafür gibts ja schließlich den zugehörigen Eintrag in der boards.txt
*.c und *.cpp (evtl auch *.S) Dateien im variants Order werden
automatisch mit kompiliert.
EAF schrieb:> Bob A. schrieb:>> Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten>> der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen>> wird.>> In dem du eine eigene variant erstellst.> Dafür gibts ja schließlich den zugehörigen Eintrag in der boards.txt> *.c und *.cpp (evtl auch *.S) Dateien im variants Order werden> automatisch mit kompiliert.
Super, Dankeschön!
Bob A. schrieb:> Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.
Ich hoffe dass du die enableExternalMemory() dabe die nicht vergessen
hast.
EAF schrieb:> Bob A. schrieb:>> Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.> Ich hoffe dass du die enableExternalMemory() dabe die nicht vergessen> hast.
Nee, die war schon noch drin, bzw. eine etwas andere Variante die aber
auch funktioniert hat.
Aktuell sieht es so aus als ob es funktioniert - evtl sogar schon immer
funktioniert hat. Nur habe ich falsche Annahmen wegen zu geringem
Wissensstand gemacht und so wie gedacht hätte es nie funktionieren
können.
Ich resümiere und bitte um Korrektur wenn ich wieder was nicht kapiert
habe:
- startup-code kann durch Verwendung von __attribute__(section)
verändert werden
- selbst wenn .data und .bss im externen Speicher liegen, dann werden
"normale" Variablen (int foo;) in den Stack lokalisiert
- in .data landen nur Variablen die entweder als static deklariert
werden oder wie im Beispiel von EAF, arrays die als Größe eine constexpr
haben
- so wie ich mir das vorgestellt habe, dass einfach alles im externen
Speicher landet, das geht gar nicht
Oliver S. schrieb:> Die XMCRA/B-Zeilen sollten da noch weg. Das Interface wird ja in der> init1-Section schon initialisiert, und das muß es auch.
Ist jetzt so, hatte vorher auch schon das Interface in .init3 und diese
Zeilen. Hat wie es scheint nichts ausgemacht.
Jetzt aber nur an einer Stelle (immer noch .init3, nicht .init1)
Bob A. schrieb:> - in .data landen nur Variablen die entweder als static deklariert> werden oder wie im Beispiel von EAF, arrays die als Größe eine constexpr> haben
Hmm, nee scheint nicht zu stimmen
1
uint32_tsomeInt;
2
uint32_tsomeOtherInt=213;
landen im internen Speicher
1
charerr_str[]="Your program has died a horrible death!";
Bob A. schrieb:> ich kapiers immer noch nicht was warum wo landet...
Tja, nicht immer hilft trail-and-error, machmal muß man lesen und
lernen.
Dein char[] landet zudem auch noch im Flash ;)
https://www.nongnu.org/avr-libc/user-manual/mem_sections.htmlBob A. schrieb:> - so wie ich mir das vorgestellt habe, dass einfach alles im externen> Speicher landet, das geht gar nicht
Für ungenutztes internes SRAm gibts eh kein Geld zurück, also kannst du
das auch verwenden. Den Stack sollte (oder muß) man da lassen, alles
andere kann ins externe Ram.
Oliver
Oliver S. schrieb:> Tja, nicht immer hilft trail-and-error, machmal muß man lesen und> lernen.
Aber ich bin doch durch Lesen zu der Annahme gekommen dass diese Art
Variablen in .data landet.
Steht ja in der avr-libc Doku so drin und ich habe genau das Beispiel
von da verwendet...
Ich raffs einfach nicht :(
Ok, dann wäre das nächste Vorschlag, ein C-Buch zu lesen. Stichworte
sind "globale", "statische", "lokale", "automatische" Variable.
Auf der einen Seite machst du da erfolgreich Experimente für
Fortgeschrittene, auf der anderen Seite fehlen dir die einfachsten
Grundlagen. Das ist schon eine seltene Mischung ;)
Oliver
Ach so, noch vergessen:
Wenn du das mit C-Buch durch hast, informier dich mal über AVR und
Strings im Flash. Es könnte sein, daß du danach dein externes Ram gar
nicht mehr brauchst.
Oliver
Bob A. schrieb:> quasi reverse knowledge aquisition lach
Evtl. solltest du anfangen im Schritttempo zu denken und nicht 5 Stufen
auf einmal nehmen.
Das kannst du erst tun, wenn du sattelfest bist.
Mjoah.... ich hab den Wink mit dem Scheunentor verstanden :)
Nichtsdestotrotz funzt es jetzt - auch die Integration in die
Arduino-Welt!
Dank allen Helfern hier!
Ich habe wieder mal viel gelernt - auch wo die eigenen Wissenslücken
sind. Eigentlich auch ganz wertvoll!
PS:
Damit der automagisch mitkompiliert Code aus dem variants-folder funzt,
muss man noch
1
#include<avr/io.h>
2
#include<avr/iomxx0_1.h>
einbinden.
Ob das so händisch-hardcoded als eine gute Idee ist?
Aber eigentlich ist es ja fest mit der Variante Atmega2560 verbandelt,
daher sollte es keine Bedarf geben dass das geändert werden muss.
PPS:
Jetzt muss ich "nur" noch besser verstehen wieso es klappt und warum es
nicht so geht wie ich anfänglich angenommen hatte.
Danke auch für den Tipp mit dem C-Buch. Werde ich beherzigen!
Hier noch der Vollständigket halber eine .zip die man unter
"arduino-sketch-.folder"/hardware extraheiren kann um die Variante mit
extra-Speicher zu bekommen.
Es wird NICHT abgefragt ob der Speicher überhaupt vorhanden ist, da muss
ich mir noch was überlegen ob und wie das möglich ist.
Bob A. schrieb:> Damit der automagisch mitkompiliert Code aus dem variants-folder funzt,> muss man noch#include <avr/io.h>> #include <avr/iomxx0_1.h>> einbinden.
Oder einfach:
#include <Arduino.h>