Nun habe ich 32kB ab 0x8000 an den ATmega2560 rangepappt und steh auf dem Schlauch, wie die beim GCC anmelden. Wie kann ich dem GCC für bestimmte Variablen (große Arrays) sagen, daß er sie dorthin legen soll? Schön wärs, wenn der GCC ihn auch nullen bzw. initialisieren kann. Die Lücke 0x2200-0x7FFF muß reserviert bleiben! Da ist nämlich kein SRAM, sondern memory mapped IO. Peter
Wie wär's, einfach einen Zeiger zu benutzen? Ansonsten kannst du das irgendwie mit sections jonglieren, wenn du unbedingt willst.
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_ext_ram http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reloc_code Wäre jetzt mein erster Ansatz. Also eine neue Linker Section anlegen an die richtige Adresse und per attribute das große Array dort hinein legen.
Jörg Wunsch schrieb: > Wie wär's, einfach einen Zeiger zu benutzen? Wenns garnicht anders geht, wäre das die Notvariante. Bloß dann muß ich mir die ganze Plazierung umständlich selber auszählen, das wollte ich vermeiden. > Ansonsten kannst du das irgendwie mit sections jonglieren, wenn du > unbedingt willst. Ja, so hatte ich es gedacht. Bin aber aus den Beispielen nicht schlau geworden. Die wollen immer gleich ab 0x2200 anfangen und dann auch nur für malloc-Variablen. Malloc will ich aber garnicht verwenden, da alle Arrays schon bekannt sind. Peter
Die Verwendung per separater Section ist doch recht einfach:
1 | #define EXTMEM __attribute__((section(".extmem")))
|
2 | |
3 | uint8_t data[100] EXTMEM; |
1 | -Wl,--section-start=.extmem=0x88000 |
Aber Achtung: keine automatische Nullung!
Peter Dannegger schrieb: > Bloß dann muß ich mir die ganze Plazierung umständlich selber auszählen, > das wollte ich vermeiden. Hmm, verstehe ich nicht ganz. Wenn das MMIO ist, dann hat man doch normalerweise alles auf vorgegebenen Adressen? Vielleicht erzählst du uns ja doch noch drei Sätze mehr dazu, was du da genau hast. Bliebe noch die Variante, alles in einer struct aufzuführen, und dann einen Zeiger auf diese zu benutzen.
Hi ein gutes Beispiel was du machen musst ist auf http://www.nongnu.org/avr-libc/user-manual/malloc.html beschrieben ab "Tunables for malloc()". Du musst im Makefile für den Linker die Startadressen von .data und .bss ändern ( --section-start,.data=0x808000, --defsym=__heap_end=0x80ffff ). Würde dann in etwa so aussehen http://www.nongnu.org/avr-libc/user-manual/malloc-x1.png. Und du must vor dem Start von main() im µC den Speicher ummappen ( MCUCR, WDTCR ). Muss in die Section ".init3" oder ".init4". Ist sehr gut auf http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=90099&start=0 beschrieben
Hab ich schonmal was zu geschrieben. Die Suchen-Funktion ist Dein Freund.
Jörg Wunsch schrieb: > Hmm, verstehe ich nicht ganz. Wenn das MMIO ist, dann hat man doch > normalerweise alles auf vorgegebenen Adressen? Vielleicht erzählst > du uns ja doch noch drei Sätze mehr dazu, was du da genau hast. Also: 0x0000 - 0x1FFF ist interner RAM für Stack und Variablen. 0x2000 - 0x7FFF sind IO-Chips dran, die werden per Pointer auf Structs adressiert. 0x8000 - 0xFFFF ist externer SRAM und da möchte ich große Arrays (Menü-Listen) ablegen. Die sollen wenn möglich vorbelegt oder genullt werden. Peter
Eduard Scheske schrieb: > ein gutes Beispiel was du machen musst ist auf > ... > Du musst im Makefile für den Linker die Startadressen von .data und .bss > ändern ( --section-start,.data=0x808000, --defsym=__heap_end=0x80ffff ). Unsinn, da steht was er machen kann, nicht was er machen muss. Wie ich Peter kenne, will er sicher nicht alle statischen Variablen in das externe RAM legen und somit den Zugriff auf diese verlangsamen.
Peter Dannegger schrieb:
> Die sollen wenn möglich vorbelegt oder genullt werden.
Diese Möglichkeit sehe ich nur, wenn du dann doch tatsächlich alles (bis
auf den Stack) in das externe RAM legst. Oder einfach am Anfang des
Programms selber initialisieren, z.B. von PROGMEM-Arrays kopieren.
Eduard Scheske schrieb: > ein gutes Beispiel was du machen musst ist auf > http://www.nongnu.org/avr-libc/user-manual/malloc.html beschrieben ab > "Tunables for malloc()". Um mal die Bilder in dem Link zu nehmen, will ich folgendes: Interner RAM bis 0x1FFF: .data_1 .bss_1 .stack Externer RAM ab 0x8000: .data_2 (mit nem Attribut angelegt) .bss_2 (mit nem Attribut angelegt) Einen .heap habe ich nicht. Peter
Lazy Leo schrieb: > Hab ich schonmal was zu geschrieben. Die Suchen-Funktion ist Dein > Freund. Die Suche nach "Lazy Leo" ergibt 0 Treffer. Peter
Stefan Ernst schrieb: >> Die sollen wenn möglich vorbelegt oder genullt werden. > > Diese Möglichkeit sehe ich nur, wenn du dann doch tatsächlich alles (bis > auf den Stack) in das externe RAM legst. Zustimmung. gcrt1.S kann nur mit einem zusammenhängenden Block .data und einem Block .bss umgehen, den Rest muss man ,,zu Fuß'' machen. Falls genügend externer SRAM vorhanden ist, kann man natürlich wirklich alles dahin legen und den internen RAM nur noch für den Stack benutzen. Leider braucht externer SRAM aber einen Takt mehr im Zugriff.
Jörg Wunsch schrieb: > Zustimmung. gcrt1.S kann nur mit einem zusammenhängenden Block > .data und einem Block .bss umgehen, den Rest muss man ,,zu Fuß'' > machen. .bss ist ja der genullte data-Bereich, kann ich nur den nach intern legen? > Falls genügend externer SRAM vorhanden ist, kann man natürlich wirklich > alles dahin legen und den internen RAM nur noch für den Stack benutzen. > Leider braucht externer SRAM aber einen Takt mehr im Zugriff. Werd ich dann wohl so machen müssen. Peter
Peter Dannegger schrieb: > .bss ist ja der genullte data-Bereich, kann ich nur den nach intern > legen? Nö, das Standard-Linkerscript verkettet .data und .bss zu einer gemeinsamen Ausgabe-Section namens .data. Ohne jetzt nachzugucken im gcrt1.S (das kannst du ggf. selbst tun) würde ich sagen, dass dieses sich auf die Symbole für den Anfang und das Ende von .bss verlässt, von daher sollte es mit einem geänderten Linkerscript gehen.
Peter Dannegger schrieb: > .bss ist ja der genullte data-Bereich, kann ich nur den nach intern > legen? Also geht es in erster Linie um die Nullung? Dann würde ich an deiner Stelle doch noch mal die Heap-Lösung in Betracht ziehen. Wenn es eher wenige große Arrays sind (und nicht viele kleine) ist der zusätzliche Speicherverbrauch minimal. Und mit calloc (statt malloc) kannst du die Arrays dann auch gleich Nullen.
Ist aber auch nichts anderes, als wenn er an den Beginn seines main() schreiben würde:
1 | memset((void *)0x8000, 0, 0x8000); |
Ja, die Nullung wäre halt nur etwas selektiver. Ich persönlich würde ja auch einfach die Lösung mit der separaten Section nehmen, und dann einmal zu Beginn selber Nullen. Aber ich habe so den Eindruck, dass ihm das irgendwie nicht zusagt.
Jörg Wunsch schrieb: > Falls genügend externer SRAM vorhanden ist, kann man natürlich wirklich > alles dahin legen und den internen RAM nur noch für den Stack benutzen. So habe ich es jetzt gemacht und es funktioniert. Damit kann man die Menüs vorbelegen. Ich hätte ja die Menüs in den Flash gelegt und wäre ohne extra SRAM ausgekommen, aber die Programmierer wollen es halt schön bequem haben. Ne Fallgrube war noch die init3-Routine, die muß used sein, sonst wird sie wegoptimiert:
1 | void init_extSRAM(void) __attribute__((used,naked,section(".init3"))); |
2 | void init_extSRAM(void) |
3 | {
|
4 | XMCRA = 1<<SRE | 1<<SRL2 | 1<<SRW00; // 0x2200 - 0x7FFF: 1 Wait |
5 | // 0x8000 - 0xFFFF: 0 Wait
|
6 | XMCRB = 1<<XMBK; // A15 .. A8 |
7 | }
|
Und der Linkerschalter:
1 | -Wl,--section-start,.data=0x808000 |
Danke an alle für die Hilfe. Peter
> die muß used sein, sonst wird > sie wegoptimiert: Nur, wenn man den "ich bin zu faul, mir beim Programmieren zu überlegen, welche Funktionen ich wirklich mal benötigen werde"-Knopf benutzt und daher -gc-sections beim Linken angibst. Dann mach der Linker natürlich genau das, was du ihm sagst: du hast die Verantwortung herauszufinden, was denn wirklich gebraucht wird, ja vom Progammierer an den Linker übertragen, und der schmeißt dann radikal alles weg, was unbenutzt aussieht. Ich verstehe ja, dass C++-Programmierer darunter leiden, dass ihnen der Compiler aus formalen Gründen zuweilen Dinge generiert, die sie dann eigentlich gar nicht brauchen, und dass man genau diese mittels -gc-sections wieder aufgeräumt bekommt, aber warum Programmierer für Microcontroller nicht in der Lage sein wollen, Funktionen, die sie gar nicht benötigen, auch gar nicht erst im Sourcecode stehen zu lassen, das leuchtet mir nach wie vor nicht ein. YMMV. ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.