Hallo Experten, ich habe ein paar grundsätzliche Fragen zum Programmieren eines µC. Ich selbst programmiere µC auf ARM Cortex-M4 Basis, falls das bei den Fragen eine Rolle spielt. - Werden lokale Variablen werden sofort nach Start des µC in den SRAM gelegt? Liegen diese liegen im Stack? - Globale Variablen werden auch sofort nach Start in den SRAM gelegt? Diese liegen glaube nicht im Stack, ist das richtig? - Wo sind constant Variablen allokiert? Liegen diese im Flash? - Gibt es Richtlinien zur Dimensionierung des Stacks? Wodurch merkt man wann er zu klein ist? Vielen Dank für eure Antworten!!
Tob75 schrieb: > Vielen Dank für eure Antworten!! alle Fragen habe nicht mit dem µC zu tun sondern mit der Programmiersprache und deren Einstellungen. Davon hast du uns aber keine Info geliefert.
Hallo, > Gibt es Richtlinien zur Dimensionierung des Stacks? Wodurch merkt man > wann er zu klein ist? Theoretisch kannst du den Stack exakt bemessen. Zunächst mal: mach ihn so gross wie möglich. Dann fülle ihn mit einem bestimmten Bitmuster, z.B. 0xAFFEAFFE oder 0xDEADBEEF oder so etwas. Und dann lass einfach deine Software laufen. Später kannst du dann z.B. mit dem Debugger schauen, bis wie weit herunter dein Bitmuster überschrieben wurde, so eine Art 'Wassermarke' oder sowas in der Art. Das war der grösste Stackverbrauch. Einerseits könnte man den also so bemessen. Andererseits könntest du auf dem PC in deiner Entwicklungsumgebung z.B. mit Doxygen oder so einen Callgraph erzeugen lassen und die tiefste Verschachtelung von Funktionen bestimmen. Da jeder Funktionsaufruf einen bestimmten Stackverbrauch mit sich zieht, kann man dann so den Stackverbrauch abschätzen. > Wo sind constant Variablen allokiert? Liegen diese im Flash? ja. > Globale Variablen werden auch sofort nach Start in den SRAM gelegt? > Diese liegen glaube nicht im Stack, ist das richtig? Nein, weil sie global sind. Die liegen 'irgendwo' im Memory. Je nach dem ob sie mit 0 initialisiert werden oder nicht liegen sie im BSS-Segment oder aber in einem anderen Segment, dessen Name mir jetzt nicht einfällt und das durch die Kopierereri im Startup-Code initialisiert wird. Genauso wie die lokalen static-Variablen in Funktionen. Die liegen im selben Segment. Aber 'normale' auto-Variablen liegen auf dem Stack. Gruss Tobias Edit: Peter II war schneller. Er hat natürlich recht, aber ich gehe mal von C aus ;-)
:
Bearbeitet durch User
Tob75 schrieb: > - Werden lokale Variablen werden sofort nach Start des µC in den SRAM > gelegt? Liegen diese liegen im Stack? Lokale Variablen liegen im Stack und werden dann angelegt, wenn sie im Programmcode deklariert werden. > - Globale Variablen werden auch sofort nach Start in den SRAM gelegt? > Diese liegen glaube nicht im Stack, ist das richtig? Globale Variablen werden beim Start in den SRAM gelegt und zwar nicht in den Stack, sondern in einen separaten Bereich für globale Variablen. (Optimierungen und Eigenheiten des Compilers ausgenommen.) > - Wo sind constant Variablen allokiert? Liegen diese im Flash? Kann, muss aber nicht sein. Wenn der Mikrocontroller nicht unkompliziert direkt wahlfrei aus dem Flash lesen kann, so wird man sie eher im RAM anlegen. > - Gibt es Richtlinien zur Dimensionierung des Stacks? Wodurch merkt man > wann er zu klein ist? Typischerweise wächst der Stack vom oberen Ende des Speichers nach unten, während alles andere von unten nach oben wächst. So kollidieren der Stack erst mit dem Rest des Speichers, wenn der Speicher randvoll ist. Das merkst du daran, dass dein Programm komplett verrückt spielt. Den Stack "dimensioniert" man somit eigentlich nicht. Man muss bloss sicherstellen, dass er nie zu gross wird. Auf einem ARM dürfte das aber ohne Rekursion fast nicht passieren.
Danke für die schnellen antworten. Und um die Info nachzureichen: Ja ich programmiere nur in C und die Entwicklungsumgebung (Rowley Crossworks) verwendet den GCC.
Tob75 schrieb: > - Wo sind constant Variablen allokiert? Liegen diese im Flash? Diese Frage hängt stark von der verwendeten Plattform und den verwendeten Werkzeugen ab. AVRs mit ihrer Harvard Architektur werden auch das im RAM ablegen. Hier bedarf es einiger Tricks (Attribute PROGMEM), um das Ganze wirklich in den Flash-Speicher zu bekommen. "const" ist überhaupt nur ein Hinweis an den Compiler (und an Mitmenschen), dass der Inhalt der Variable nicht verändert wird. Dadurch kann der Compiler vor Dummheiten warnen und ggf. Optimierungen durchführen. In erster Linie kann man sich das aber wie "normale" Variablen vorstellen. Mit freundlichen Grüßen, Karol Babioch
Tobias Plüss schrieb: > Theoretisch kannst du den Stack exakt bemessen. Zunächst mal: mach ihn > so gross wie möglich. Dann fülle ihn mit einem bestimmten Bitmuster, > z.B. 0xAFFEAFFE oder 0xDEADBEEF oder so etwas. Und dann lass einfach > deine Software laufen. Später kannst du dann z.B. mit dem Debugger > schauen, bis wie weit herunter dein Bitmuster überschrieben wurde, so > eine Art 'Wassermarke' oder sowas in der Art. Das war der grösste > Stackverbrauch. Gefährlicher Ansatz. Hierbei ist nicht sichergestellt, daß der worst case während der Prüfzeit überhaupt aufgetreten ist. Also besser ganz schnell wieder vergessen. > Andererseits > könntest du auf dem PC in deiner Entwicklungsumgebung z.B. mit Doxygen > oder so einen Callgraph erzeugen lassen und die tiefste Verschachtelung > von Funktionen bestimmen. Schon besser, aber immer noch nur die halbe Miete. Der Stackverbrauch von Interrupts muß gesondert berücksichtigt werden.
c-hater schrieb: >> Andererseits >> könntest du auf dem PC in deiner Entwicklungsumgebung z.B. mit Doxygen >> oder so einen Callgraph erzeugen lassen und die tiefste Verschachtelung >> von Funktionen bestimmen. > > Schon besser, aber immer noch nur die halbe Miete. Der Stackverbrauch > von Interrupts muß gesondert berücksichtigt werden. zzgl. Rekursion...
c-hater schrieb: >> Später kannst du dann z.B. mit dem Debugger schauen, bis wie weit >> herunter dein Bitmuster überschrieben wurde, so eine Art 'Wassermarke' >> oder sowas in der Art. Das war der grösste Stackverbrauch. > > Gefährlicher Ansatz. Hierbei ist nicht sichergestellt, daß der worst > case während der Prüfzeit überhaupt aufgetreten ist. Immer noch besser als die Art, wie es normalerweise ermittelt wird, nämlich gar nicht. >> Andererseits könntest du auf dem PC in deiner Entwicklungsumgebung z.B. >> mit Doxygen oder so einen Callgraph erzeugen lassen und die tiefste >> Verschachtelung von Funktionen bestimmen. > > Schon besser, aber immer noch nur die halbe Miete. Der Stackverbrauch > von Interrupts muß gesondert berücksichtigt werden. Und den Aufwand gibst du dir für jedes Programm?
Mal von C und ähnlichen Sprachen ausgehend, üblicherweise: Tob75 schrieb: > - Werden lokale Variablen werden sofort nach Start des µC in den SRAM > gelegt? Nein. Der Platz wird meist am Anfang einer Funktion auf dem Stack angelegt und mit Beendigung wieder freigegeben. Drum ist es ein Stack. Ausnahme: Lokale Variablen mit "static" dran. Die sind vom Speicher her wie globale Variablen, aber nur in der Funktion selbst per Name ansprechbar. > Liegen diese liegen im Stack? Ja. Ausnahme sind kleine µC wie z.B. 8051 und PIC16, die sich mit der Verwendung von Stacks als Speicher für Variablen etwas schwer tun, und deren Compiler deshalb auch lokale Variablen gerne statisch anlegen, ggf. überlappend. > - Globale Variablen werden auch sofort nach Start in den SRAM gelegt? > Diese liegen glaube nicht im Stack, ist das richtig? Ja. > - Wo sind constant Variablen allokiert? Liegen diese im Flash? Keine generelle Regel. Aber als Daumenregel kann man wohl sagen, dass dies nur der Fall ist, wenn das Flash im Datenadressraum liegt. Bei 32-Bittern ist das üblich, bei kleineren teils nicht. > - Gibt es Richtlinien zur Dimensionierung des Stacks? Wodurch merkt man > wann er zu klein ist? Das er überläuft. :-) Im Ernst: es gibt keine Regel dafür wie sich das äussert. In vielen Umgebungen laufen Stack und Heap / statische Daten gegeneinander, weshalb ein überbordender Stack zunächst in den Heap und dann in die statischen Daten reinläuft und da Chaos anrichtet. Aber es gibt auch andere Umgebungen.
:
Bearbeitet durch User
Tob75 schrieb: > - Wo sind constant Variablen allokiert? Liegen diese im Flash? konstante auto-Variable liegen (immer?) auf dem Stack.
Steffen Rose schrieb: > konstante auto-Variable liegen (immer?) auf dem Stack. Oder nirgends. Oder werden statisch angelegt, weil sie als unveränderlich nicht reentrant sein müssen:
1 | int g(const int *); |
2 | |
3 | int f(void) |
4 | {
|
5 | const int x[2] = { 1, 2 }; |
6 | return g(x); |
7 | }
|
1 | f: |
2 | subl $12, %esp |
3 | movl $x.1281, (%esp) |
4 | call g |
5 | addl $12, %esp |
6 | ret |
7 | x.1281: |
8 | .long 1 |
9 | .long 2 |
Lokale Variablen liegen je nach Prozessor auch in Registern, ohne dass auf dem Stack dafür Platz angelegt werden muss. Oder sie liegen nirgends, weil vollständig wegoptimiert.
:
Bearbeitet durch User
Ja stimmt. Hatte nur die Postings im Kopf, dass diese häufig im Flash liegen und wollte dem widersprechen.
Steffen Rose schrieb: > Tob75 schrieb: >> - Wo sind constant Variablen allokiert? Liegen diese im Flash? > > konstante auto-Variable liegen (immer?) auf dem Stack. Konstante Variablen?
unveränderliche Variable (versteht so bloß keiner, was gemeint ist) Edit: ok, auch nicht viel besser. Ich wollte auf den Unterschied zwischen Konstanten mit automatic storage und static Konstanten aufmerksam machen.
:
Bearbeitet durch User
Bernhard D. schrieb: > Konstante Variablen? Stimmt schon. Leider. In C ist const int n = 10; keine lexikalische Konstante, sondern tatsächlich eine unveränderliche Variable. In C++ ist das etwas anders (und komplizierter :-).
@ P. M. (o-o) >Typischerweise wächst der Stack vom oberen Ende des Speichers nach >unten, während alles andere von unten nach oben wächst. So kollidieren >der Stack erst mit dem Rest des Speichers, wenn der Speicher randvoll >ist. Das merkst du daran, dass dein Programm komplett verrückt spielt. Naja, manchmal hat man aber auch Pech und es kommt zu Fehlern, die lange nicht auffallen, z.B. weil eine maximale Stacktiefe nur selten erreicht wird oder nur kleine Fehler passieren aber kein Absturz bzw. massives Fehlverhalten. Wäre das nicht ein wichtiges Feature für CPUs, eine Stackprüfung in HARDWARE? Oder wenigstens in Software? Und damit meine ich nicht den Trick mit dem Füllmuster, sondern eine automatische Prüfung des Stacks bei jedem Funktionsaufruf!
Falk Brunner schrieb: > Wäre das nicht ein wichtiges Feature für CPUs, eine > Stackprüfung in HARDWARE? Oder wenigstens in Software? Und damit meine > ich nicht den Trick mit dem Füllmuster, sondern eine automatische > Prüfung des Stacks bei jedem Funktionsaufruf! Ja, das fände ich auch wichtig. Ein Stack-Underrun-Interrupt bzw. eine Exception sollte sich mit einem einfachen Compare realisieren lassen. Gibt es Architekturen, die sowas schon unterstützen? Wie sieht eine brauchbare Realisierung in Software aus? Eine Abfrage bei jedem Funktionsaufruf dürfte zuviel Performance kosten. Mark
Falk Brunner schrieb: > Wäre das nicht ein wichtiges Feature für CPUs Ausserhalb der kleinen µC-Sphäre lässt sich das oft mühelos über die Speicherverwaltung erledigen. Also indem der Stack sein Ende in einem finalen page fault findet. Der Compiler muss dann nur drauf achten, dass bei grossen lokalen Daten die guard page nicht übersprungen wird, muss also ggf. bei Arrays entsprechende Zugriffe alle paar KB einflechten. > Oder wenigstens in Software? Gibts in GCC im Prinzip, wobei es natürlich Sache der Zielsystemanpassung ist, etwas draus zu machen.
:
Bearbeitet durch User
P. M. schrieb: > Typischerweise wächst der Stack vom oberen Ende des Speichers nach > unten Bei den 16-Bittern von Microchip, also PIC24/30/33, wächst der Stack aufwärts. Irgendwas macht Microchip eben immer anders. ;-)
:
Bearbeitet durch User
Rolf Magnus schrieb: > Und den Aufwand gibst du dir für jedes Programm? Natürlich. Ich bin der Programmierer und deshalb nicht nur dafür verantwortlich, sondern auch dazu in der Lage. Wer sonst sollte das denn deiner Meinung nach tun? Der Pförtner?
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.