Forum: Mikrocontroller und Digitale Elektronik Warum wird SP unnötig initialisiert? (AVR-GCC, Attiny841)


von Tuxpilot (Gast)


Lesenswert?

Hallo!

Ich habe gestern mal avr-gcc 4.9.2 (von packages.ubuntu.com für xenial, 
inklusive avr-libc und binutils-avr) ausprobiert und das 
Beispielprogramm aus dem AVR-GCC-Tutorial (mit dem Makefile von dort) 
für den Attiny841 übersetzt.

In main.lss habe ich folgendes entdeckt:
1
...
2
...
3
  3a:  08 c0         rjmp  .+16       ; 0x4c <__bad_interrupt>
4
5
0000003c <__ctors_end>:
6
  3c:  11 24         eor  r1, r1
7
  3e:  1f be         out  0x3f, r1  ; 63
8
  40:  cf ef         ldi  r28, 0xFF  ; 255
9
  42:  d2 e0         ldi  r29, 0x02  ; 2
10
  44:  de bf         out  0x3e, r29  ; 62
11
  46:  cd bf         out  0x3d, r28  ; 61
12
  48:  02 d0         rcall  .+4        ; 0x4e <main>
13
  4a:  06 c0         rjmp  .+12       ; 0x58 <_exit>
14
15
0000004c <__bad_interrupt>:
16
  4c:  d9 cf         rjmp  .-78       ; 0x0 <__vectors>
17
18
0000004e <main>:
19
...
20
...
Wie man sieht, wird der Stackpointer mit RAMEND initialisiert. (40–46) 
Aber warum? Das ist doch sinnlos, da der Attiny841 SP sowiesor mit 
RAMEND initialisiert.

Wenn ich „volatile uint8_t blabla;“ und „blabla++“ dazuschreibe, wird 
die Variable tatsächlich aus dem SRAM geladen, jedoch nicht etwa von 
hinter dem Stack. Scheinbar beginnt der Stack also immer bei RAMEND.

Kann man auf diese unnütze Initialisierung verzichten?

Gruß, Tuxpilot

P. S.: Natürlich ist diese Frage nicht so wichtig, ich wundere mich 
nur...

von c-hater (Gast)


Lesenswert?

Tuxpilot schrieb:

> Kann man auf diese unnütze Initialisierung verzichten?

Natürlich. Aber eben nur bei den Targets, bei denen sie wirklich unnütz 
ist. Tiny841 ist so eins, andere sind's nicht. Vor allem ältere 
natürlich, die das einfach noch nicht in Hardware eingebaut haben. Z.B. 
Mega8, 16, 32, 1280, 2560 und sicher auch ein ganze Menge älterer Tinys, 
ganz sicher z.B. der (wegen seiner UART) recht häufig verwendete 2313.

Letzte Sicherheit, ob der Stackpointer bereits durch die Hardware 
sinnvoll initialisiert wird, liefert (natürlich) das Datenblatt des 
Target...

Im Übrigen sollte man nicht vergessen, dass diese hardwaremäßige 
Initialisierung des SP auch nur bei einem Hardware-Reset passiert. 
Manchmal ist es aber z.B. durchaus nützlich, nur eine Art "Soft-Reset" 
auszuführen, also einen unbedingten Sprung zum Reset-Vektor. Bootloader 
sind ein typische Anwendung dafür, zumindest die, die von kompetenten 
Leuten so geschrieben wurden, dass sie ordentlich hinter sich aufräumen, 
bevor sie die geladene App anspringen. Bei denen gehört dann natürlich 
auch zum Job, den SP neu zu initialisieren, wenn sie sich nicht darauf 
verlassen können, dass die App oder deren Runtime-Umgebung das tut. Ich 
hoffe, du schreibst auch deine Bootloader selbst und kompetent...

von Peter D. (peda)


Lesenswert?

Tuxpilot schrieb:
> Aber warum? Das ist doch sinnlos, da der Attiny841 SP sowiesor mit
> RAMEND initialisiert.

Die ersten AVRs (AT90Sxxx) hatten das noch nicht, nach dem Reset zeigte 
SP auf 0x0000. Auch wenn die schon ewig keiner mehr verwendet, blieb das 
SP setzen im AVR-GCC drin. Wie auch die unglückliche Verwendung von 
R0,R1.

von Tuxpilot (Gast)


Lesenswert?

c-hater schrieb:
> Ich
> hoffe, du schreibst auch deine Bootloader selbst und kompetent...

Ach so, macht Sinn. An Bootloader habe ich noch nicht gedacht.

Nee, ich schreibe keine Bootloader. Wenn ich den auf den AVR 
programmieren kann, dann kann ich auch gleich das fertige Programm 
nehmen...

Dann hör ich jetzt auf mich zu wundern, danke für die Auskunft.
Wenn mir mal wieder 8000mB fehlen, kann ich das ja noch wegmachen.*


* mB = millibyte ;)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Tuxpilot schrieb:
> In main.lss habe ich folgendes entdeckt:
>
1
>   3c:  11 24         eor  r1, r1
2
>   3e:  1f be         out  0x3f, r1  ; 63
3
>   40:  cf ef         ldi  r28, 0xFF  ; 255
4
>   42:  d2 e0         ldi  r29, 0x02  ; 2
5
>   44:  de bf         out  0x3e, r29  ; 62
6
>   46:  cd bf         out  0x3d, r28  ; 61
7
>   48:  02 d0         rcall  .+4        ; 0x4e <main>
8
>   4a:  06 c0         rjmp  .+12       ; 0x58 <_exit>
9
>
> Wie man sieht, wird der Stackpointer mit RAMEND initialisiert. (40–46)

Nicht wirklich, SP wird mit dem Wert des Symbols __stack initialisiert, 
das per default auf RAMEND sitzt.

Grund 1: Wenn also SP auf einen anderen Wert initilisiert werden soll, 
dann geht das z.B. ohne Neucompilierung per
1
avr-gcc ... -Wl,--defsym,__stack=0x200

> Aber warum? Das ist doch sinnlos, da der Attiny841 SP sowiesor mit
> RAMEND initialisiert.

Grund 2: Es gibt Leute, die per "goto 0" einen "Neustart" des µC 
veranstalten, z.B. von einem Bootloader zur Anwendung springen.

> Kann man auf diese unnütze Initialisierung verzichten?

Wenn du sie nicht brauchst, ja.  Du kannst dir deinen eigenen 
Startup-Code klöppeln und verwenden; allerdings braucht's dazu mehr als 
-nostartfiles weil ein Teil des Startup-Codes traditionell aus der 
libgcc stammt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Siehe auch

https://savannah.nongnu.org/bugs/?45701

für einen entsprechenden avr-libc Report.

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
Noch kein Account? Hier anmelden.