Ähm gerade fällt mir zum ersten Mal auf, daß mein avr-gcc munter Fantasieadressen über die RAM-Grenzen hinaus produziert. Man merkts nur daran, daß das Programm dann nicht so toll läuft. Blöde Frage aber ist das normal, daß man da selbst aufpassen muß, daß die data+bss-sections nicht größer als der vorhandene RAM des AVR werden? Ich meine bei Überschreiten der text-section meckern ja sowohl avr-gcc wie auch avrdude aber beim RAM nix? Jetzt bin ich leicht verwirrt. Aus dem .sym beim ATmega328p: 00800100 D __data_start ... 00800923 B __bss_end 00800923 B _end
batman schrieb: > Blöde Frage aber ist das normal, Ja, ist es: der Linker kennt praktisch nur Device-Klassen, daher kann er die Limits des konkreten Devices nicht kennen. Er würde dir allerdings meckern, wenn du mehr als 64 KiB versuchst zu allozieren.
Achso na dann. Der Stack kommt ja sowieso noch darüber am RAM-Ende mit unbekannter Größe oder? Ist das Mist, wenn man ans RAM-Limit kommt.
batman schrieb: > Der Stack kommt ja sowieso noch darüber am RAM-Ende mit unbekannter > Größe oder? Ja, der Stack wächst (per default) vom Ende des SRAMs nach unten, die Variablen dagegen vom Anfang nach oben. Irgendwann „treffen“ sie sich dann also.
Das alte Dilemma. Kann ich im C-Programm einen Test-String als letzte globale Variable, also quasi als Puffer anlegen oder läßt sich der Linker bei der Adressvergabe nicht reinreden?
batman schrieb: > oder läßt sich der Linker bei der Adressvergabe nicht reinreden? Weder Compiler noch Linker lassen sich durch irgendeine Anordnung von irgendwas innerhalb deines Quelltextes beeindrucken. Du kannst natürlich im Linker eine Guard-Variable explizit hinter dem Rest platzieren, indem du sie im Compiler in eine eigene Section packst und im Linkerscript dann arrangierst, dass genau diese Section am Ende des statisch allozierten RAMs liegt.
Kann man die RAM-Größe nicht im Linker-Script angeben? Genau wie die Größe des Flash? Mit dem arm-gcc geht's hier ungefähr so:
1 | MEMORY
|
2 | {
|
3 | flash_boot (rx) : ORIGIN = 0x08000000, LENGTH = 16K |
4 | flash_display (rx) : ORIGIN = 0x08008000, LENGTH = 24K |
5 | |
6 | ram_boot (rw) : ORIGIN = 0x2001c000, LENGTH = 1K |
7 | ram_display (rw) : ORIGIN = 0x2001f000, LENGTH = 2K |
8 | }
|
9 | |
10 | SECTIONS
|
11 | {
|
12 | .text : ALIGN(16) SUBALIGN(16) { |
13 | FILL (0xff) |
14 | *(.text) |
15 | *(.text.*) |
16 | *(.rodata) |
17 | *(.rodata.*) |
18 | *(.gcc*) |
19 | . = ALIGN(4); |
20 | text_end = .; |
21 | } > flash_display |
22 | |
23 | .stack : { |
24 | stack = .; |
25 | . += 768; |
26 | tos = .; |
27 | } > ram_display |
28 | |
29 | .data : ALIGN(4) SUBALIGN(4) { |
30 | data_start = .; |
31 | *(.data) |
32 | *(.data*) |
33 | data_end = .; |
34 | } > ram_display AT > flash_display |
35 | |
36 | .bss : ALIGN(4) SUBALIGN(4) { |
37 | bss_start = .; |
38 | *(COMMON) |
39 | *(.bss) |
40 | *(.bss*) |
41 | bss_end = .; |
42 | } > ram_display |
43 | }
|
Vielleicht funktioniert es deshalb, weil ich den Stack an den Anfang lege?
eagle user schrieb: > Kann man die RAM-Größe nicht im Linker-Script angeben? Natürlich kann man. AVR-GCC ist aber deutlich mehr „out of the box“ als ARM-GCC; einen Linkerscript gibt man dort daher normalerweise nicht selbst an. Die generischen Linkerscripts funktionieren gut genug im Zusammenspiel mit dem Startup-Code der avr-libc, als dass man das alles direkt benutzen kann. Diese generischen Linkerscripts sind aber eben, wie ich eingangs schrieb, nicht pro Device vorhanden, sondern nur grob klassifiziert für jede eigene AVR-Klasse. Gegen das genannte Problem der Kollision des Stacks mit den statisch zugewiesenen Daten würde der Linkerscript ohnehin nicht helfen. Es bleibt damit immer beim Programmierer abzuschätzen, ob der nach dem Linken vorhandene freie RAM aller Wahrscheinlichkeit nach ausreichend für den Stack sein wird.
Absolut richtig. Ich hätte das Problem nur einen Tag früher erkannt, wenn es eine RAM-Overflow-Warnung gegeben hätte. Einen Overflow des (wg. RTOS) minimalen main-Stacks hatte ich nicht auf dem Schirm.
batman schrieb: > wenn es eine RAM-Overflow-Warnung gegeben hätte Daher gab's bei WinAVR immer noch so einen Script, der nach dem Compilieren den Füllstand der Speicher in % ausgegeben hat. Hat Eric Weddington dann als schrägen Hack ins "size"-Programm hinein gelegt, aber es war von vornherein klar, dass dieser rein AVR-spezifische Hack es niemals hätte (in dieser Form) in die Binutils zurück gemacht. Die Shellscript-Variante bliebe natürlich nach wie vor. Vorteil ist, dass man auch die Sache mit dem Stack dann schnell abschätzen lernt.
:
Bearbeitet durch Moderator
gcc -fstack-usage benutzen und dann immer schön die *.su Dateien lesen? Oder -Wstack-usage=200 fürs gröbste..
Jörg W. schrieb:
Und wozu ist das ganze Geraffel dann gut, dass crt.o nach .note.gnu.avr
packt?
1 | .section .note.gnu.avr.deviceinfo, "", @note |
2 | #define NOTE_NAME "AVR" |
3 | #ifdef __AVR_DEVICE_NAME__ |
4 | #define DEVICE_NAME STR(__AVR_DEVICE_NAME__) |
5 | #else |
6 | #define DEVICE_NAME "" |
7 | #endif |
8 | |
9 | .long .L__note_name_end - .L__note_name_start |
10 | .long .L__desc_end - .L__desc_start |
11 | .long 1 ; Type 1 - this is the only known note type for AVR. |
12 | .L__note_name_start: |
13 | .asciz NOTE_NAME |
14 | .balign 4 |
15 | .L__note_name_end: |
16 | .L__desc_start: |
17 | #ifdef FLASHSTART |
18 | .long FLASHSTART |
19 | #else |
20 | .long 0 |
21 | #endif |
22 | #ifdef PROGMEM_SIZE |
23 | .long PROGMEM_SIZE |
24 | #elif FLASHEND > 0 |
25 | .long FLASHEND + 1 |
26 | #else |
27 | .long FLASHEND |
28 | #endif |
29 | .long RAMSTART |
30 | #ifdef RAMSIZE |
31 | .long RAMSIZE |
32 | #elif RAMEND > 0 |
33 | .long RAMEND - RAMSTART + 1 |
34 | #else |
35 | .long RAMEND |
36 | #endif |
37 | #ifdef E2START |
38 | .long E2START |
39 | #else |
40 | .long 0 |
41 | #endif |
42 | #ifdef EEPROM_SIZE |
43 | .long EEPROM_SIZE |
44 | #elif E2END > 0 |
45 | .long E2END + 1 |
46 | #else |
47 | .long E2END |
48 | #endif |
49 | /* String offsets table. |
50 | Index 0 - Size of offset table in bytes |
51 | Index 1 - Device name byte offset |
52 | */ |
53 | .L__stroffsettab_start: |
54 | .long .L__stroffsettab_end - .L__stroffsettab_start /* Size of index table in bytes */ |
55 | .long .L__device_name_start - .L__strtab_start /* Byte offset of device name */ |
56 | .L__stroffsettab_end: |
57 | /* String table for storing arbitrary strings. |
58 | Offsets are stored in the string offset table above */ |
59 | .L__strtab_start: |
60 | .byte 0 |
61 | .L__device_name_start: |
62 | .asciz DEVICE_NAME |
63 | .L__device_name_end: |
64 | .byte 0 |
Aus: http://svn.savannah.nongnu.org/viewvc/avr-libc/trunk/avr-libc/crt1/gcrt1.S?view=markup Ich hätte gedacht, dass dass ganau dafür eingeführt wurde? Immerhin ist nie erforderliche Info da.
Jo, könnte sein, dass das dafür mal da war – dann aber nicht richtig zu Ende geführt worden ist. Könnte man sich wohl zumindest hinsetzen und es darauf basierend korrekt machen, anders als der schräge, hart codierte Hack von Eric dazumals.
Die aktuelleln Versionen vom AtmelStudio geben immer noch einen Meldung aus:
1 | Program Memory Usage : 140188 bytes 13,4 % Full |
2 | Data Memory Usage : 74200 bytes 56,6 % Full |
Im automatisch genereierten Makefile kann man aber keinen Aufruf dafür erkennen. Weiß jemand wie das funktioniert? Ich würde die Ausgabe gerne in meinen manuellen MakeFiles einbauen
Aber immer schon dran denken, dass avr-size nur den Speicherbedarf für statische Variablen berücksichtigt. Der Stack und dynamischer Speicher sind nicht mit drin. Ich würde daher stets dafür sorgen, dass mindestens 64 Bytes frei bleiben. Wenn man printf benutzt, dann mindestens 100 Bytes.
Hi, aber man kann sich doch beliebige neue Speicherklassen im Linkerfile erzeugen, explizit seine Variablem lokatieren und diese Klassen auf Grösse überwachen. Dann spukt der Linker die entsprechenden Fehler aus...
1 | .calram (NOLOAD) : |
2 | {
|
3 | PROVIDE (__calram_start = .) ; |
4 | *(.calram*) |
5 | PROVIDE (__calram_end = .) ; |
6 | } > data |
7 | .data : AT (ADDR (.text) + SIZEOF (.text)) |
8 | {
|
9 | PROVIDE (__data_start = .) ; |
10 | *(.data) |
11 | *(.data*) |
12 | *(.rodata) /* We need to include .rodata here if gcc is used */ |
13 | *(.rodata*) /* with -fdata-sections. */ |
14 | *(.gnu.linkonce.d*) |
15 | . = ALIGN(2); |
16 | _edata = . ; |
17 | PROVIDE (__data_end = .) ; |
18 | } > data |
19 | ASSERT((ADDR(.calram) + SIZEOF(.calram)) <= ADDR(.data), ".calram exceeds page size") |
Grüße
adkfsgksadf@gmx.de schrieb: > aber man kann sich doch beliebige neue Speicherklassen im Linkerfile > erzeugen, Klar kann man das. Aber nochmal: „normale“ AVR-Nutzer mögen sich eher nicht um den Linkerscript kümmern, denn der, der mit der Toolchain mitkommt, deckt einen Großteil der Bedürfnisse ab. Wie schon ausreichend dargelegt worden ist, muss man sowieso extern den Speicherfüllstand im Blick behalten, damit man ausreichend Reserve für den Stack hat. (Der Heap gibt sich selbst Mühe, immer noch genügend Abstand zum Stack als Reserve zu haben.) > Dann spukt der Linker die entsprechenden Fehler > aus... Na, hoffentlich spukt er nicht … Halloween ist ja schon vorbei. :)
Beitrag #5220899 wurde von einem Moderator gelöscht.
Ich hab das Feature auch jahrelang nicht vermißt, also ist das schon zu verschmerzen, wenns der Einfachheit dient.
es gab da mal avrStackView der bekommt das erstaunlich gut hin. Stefan
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.