Hallo zusammen, ich stehe vor einer kleinen Herausforderung, die mir so neu ist. Ich habe ein kleines Projekt für einen Attiny 2313A aufgesetzt. Das Projekt besteht - mehr oder weniger - aus zwei unabhängigen Teilen: 1) Kommunikation mit einem Master via MODBUS-ASCII 2) Auslesen von Sensoren via I2C Ich habe für die Entwicklung die beiden Teile unabhängig programmiert und erfolgreich getestet. Beide Teile zusammen erzeugen leider unsinnige Ergebnisse. Meine Vermutung ist, dass es etwas mit doppelter Belegung des Speichers zu tun hat. Leider bemerkte ich dann auch, dass schon Optimierung "-Os" aktiviert war. AVR-GCC meldet auch ca. 98% ROM-Auslastung. Ich habe versucht mit "-O1" zu kompilieren, was jedoch mit Fehler abbricht ("Program memory 114% Full"). Ich habe schon alle konstanten als "const" angelegt und alle Variablen als "static". Habt ihr schon mal ähnliches Erlebt? Habt ihr einen Tipp, wie man die Sache angehen kann? Zur Not würde ich auf den Attiny 4313 umsteigen. Viele Grüße, Alex
Alex B. schrieb: > AVR-GCC meldet auch ca. 98% ROM-Auslastung. ist doch ok. Flash wird zur Laufzeit nicht gebraucht. > Beide Teile zusammen erzeugen leider unsinnige Ergebnisse. Meine > Vermutung ist, dass es etwas mit doppelter Belegung des Speichers zu tun > hat. kann nur passieren, wenn du selber den Speicher vergibst, wenn es der GCC macht (was üblich bei C ist) dann passiert das nicht.
Timing? Doppelte Interrupt- bzw. Timer-nutzung?
Hallo Alex, zum Glück gibt es ja noch einen größern attiny mit 4kB Flash. Hast Du modular Programmiert und saubere Schnittstellen zwischen den Modulen festgelegt ? Zeig uns doch einfach mal den gesamten Code und Schaltplan.
Uwe S. schrieb: > zum Glück gibt es ja noch einen größern attiny mit 4kB Flash. damit wird das Problem aber nicht automatisch verschwinden.
Peter II schrieb: > Uwe S. schrieb: >> zum Glück gibt es ja noch einen größern attiny mit 4kB Flash. > > damit wird das Problem aber nicht automatisch verschwinden. Das habe ich auch nicht behauptet.
Uwe S. schrieb: > Peter II schrieb: >> Uwe S. schrieb: >>> zum Glück gibt es ja noch einen größern attiny mit 4kB Flash. >> >> damit wird das Problem aber nicht automatisch verschwinden. > > Das habe ich auch nicht behauptet. Vielen Dank für die ganzen Antworten bisher! Uwe S. schrieb: > Hast Du modular Programmiert und saubere Schnittstellen zwischen den > Modulen festgelegt ? Hatte ich. Ich schmeiße aber gerade "alles in eine main()". Vorher hatte ich ein paar globale Variablen und die waren zum Teil "extern" deklariert. Uwe S. schrieb: > zum Glück gibt es ja noch einen größern attiny mit 4kB Flash. Das ist auch meine Nofall-Lösung. Uwe S. schrieb: > Zeig uns doch einfach mal den gesamten Code und Schaltplan. Damit warte ich mal noch ein bisschen... Ich will eure wertvolle Zeit nicht damit vergeuden in meinem Code einen Fehler zu finden... Viele Grüße, Alex
Na dann sehen wir auch davon ab, unsere Zeit mit wildem herumraten zu vergeuden.
Ausreichend neuen Compiler benutzen: "avr-GCC -v" sollte 4.8.2 oder größer melden. Compiler und Linker mit "-flto -Os" füttern, dann läuft der Optimizer über das ganze Programm. Compiler probeweise mit "-mcall-prologues" füttern, das kann bei vielen Funktionen mit hoher Registerlast den Flash-Bedarf (bei minimaler Laufzeiterhöhung) verringern. Static-Variablen müssen nicht gut sein, wenn sie nicht wirklich weiterleben müssen und jedesmal neu initialisiert werden, dann kann das auch nach hinten losgehen. Da hilft eine
1 | #define FAKE_STATIC static
|
2 | //#define FAKE_STATIC
|
3 | ...
|
4 | void foo() { |
5 | FAKE_STATIC int8_t tmp=1; |
6 | ...
|
7 | }
|
um beide Varianten schnell durchzuprobieren.
Stefan U. schrieb: > Na dann sehen wir auch davon ab, unsere Zeit mit wildem herumraten zu > vergeuden. Was sagt man dazu... angespornt durch diese Aussage habe ich mich daran gemacht den Code besser lesbar zu machen und habe ihn weiter in kleinere Funktionen unterteilt. Außerdem habe ich alle Variablen als "nicht-static" erstellt. Das Ergebnis: Program Memory Usage : 1858 bytes 90,7 % Full Data Memory Usage : 94 bytes 73,4 % Full EEPROM Memory Usage : 1 bytes 0,8 % Full Das Programm ist ein paar Prozent kleiner. Aber viel wichtiger: Es läuft! Erklären kann ich es mir nicht. Optimierung steht nun auf "-Os". Für den Fall, dass sich dennoch jemand das Projekt anschauen möchte und ggf. ein paar Tipps hat, wie man die Performance noch verbessern kann, habe ich mal die Quelldateien angehängt. Ich werde es jetzt mal ein paar Stunden laufen lassen um zu sehen, ob es auch dauerhaft stabil läuft... Danke euch allen und viele Grüße, Alex
Na Herzlichen Glückwunsch. Du hast soeben gelernt, dass es sich lohnt, seine Arbeit gut zu strukturieren.
> Erklären kann ich es mir nicht.
Manchmal liegt es an Stack überlauf. Hier im Forum wurden schon merhamls
Tips gegeben, wie man Stack Überlauf mit ein paar Zeilen Code zur
Laufzeit erkennen kann. Such mal danach. Du brauchst es zwar jetzt
gerade nicht mehr, aber das kommt irgendwann wieder.
Alex B. schrieb: > Aber viel wichtiger: Es läuft! > > Erklären kann ich es mir nicht. Kann gut sein, daß durch die Strukturierung weniger RAM verbraucht wird. 34 Byte Stack ist nicht gerade viel.
Peter D. schrieb: > Alex B. schrieb: >> Aber viel wichtiger: Es läuft! >> >> Erklären kann ich es mir nicht. > > Kann gut sein, daß durch die Strukturierung weniger RAM verbraucht wird. > 34 Byte Stack ist nicht gerade viel. Insgesamt sollen später ca. 20 Bus-Knoten am Modbus hängen. Der hier beschriebene war der erste Prototyp. Für die "Serie" werde ich dann doch lieber den Attiny4313 bestücken. Dann kann ich auch noch mal ohne Optimierung kompilieren lassen und vergleichen... Vielen Dank und viele Grüße, Alex
Ist der gepostete Code der letzte Stand? Da sind nämlich immer noch diverse static Variablen in Funktionen, die wohl eher nicht statisch sind, da sie, bevor sie erstmals gelesen werden, überschrieben werden. Wenn man eh zuwenig RAM hat, dann reservieren die dauerhaft Platz (und der Compiler benutzt sie eventuell (fast) gar nicht). Gefährlich wird's dann, wenn man meint, man hätte sie initialisiert. Das passiert in der Form
1 | void foo() { |
2 | Static int i=0; |
3 | ...
|
4 | }
|
nämlich nur einmal. Beim Programmstart. Danach macht man mit den Hinterlassenschaften des letzte foo()-Aufrufs weiter. Wer das nicht vorher wußte, der tut sich auch mit dem debuggen schwer. modbus_calcLRC() benutzt z.B. diesen "Trick" um die Prüfsumme über ALLE bisher geprüften Nachrichten zu berechnen. Das geht wohl nur einmal.
Hallo Alex, ich habe schon die Uart Interruput Routinen für TX und RX gesucht und sie nicht direkt gefunden. Und im File Modbus.c sind sie. Aua: a) cli / sei in einer Interruputroutine - warum ? b) was bezweckst Du mit dem Return, das ist überflüssig !
1 | //USART (RS485) received character interrupt
|
2 | ISR(USART_RX_vect){ |
3 | cli(); |
4 | modbusProccessRxChar(UDR); //interrupt is cleared automatically upon read of UDR |
5 | sei(); |
6 | return; |
7 | }
|
8 | |
9 | //USART (RS485) transmit data completed interrupt
|
10 | ISR(USART_TX_vect){ |
11 | cli(); |
12 | ; //interrupt is cleared automatically upon execution of this interrupt |
13 | |
14 | //check if last Byte was transmitted. If yes, disable Line-Driver to free RS485 lines
|
15 | if(modbusStatReg.pendingTxBytes == 0){ |
16 | PORTD &= ~(1<<RS485_DE); //disable driver |
17 | PORTD &= ~(1<<RS485_NRE); //enable receiver |
18 | }
|
19 | sei(); |
20 | return; |
21 | }
|
Das sieht mehr nach zu wenig RAM aus, was dann zum Stack überlauf führen kann. Ein Problem sind da z.B. Aufrufe von funktionen in ISRs, insbesondere solchen die nicht als Static deklariert sind. Das braucht unnötig viel Platz auf dem Stack. Wenn es wegen der Übersicht mit funktionen sein soll, dann bevorzugt als static inline ... . Flash Speicher scheint ja jetzt vorhanden zu sein. Das SEI() in der ISR ist gefährlich. Es erlaubt verschaltelte Interrupts und damit zusätzlichen Bedarf an Platz auf dem Stack. Nötig ist es so wie gezeigt nicht (die Freigabe kurz vor ende bringt fast keinen Vorteil), und erzeugt die Gefahr selten auftretender und damit schwer zu findender Fehler.
> Initialisierung... Das passiert in der Form
1 | void foo() { |
2 | Static int i=0; |
3 | ... |
4 | } |
> nämlich nur einmal. Das dachte ich auch bis vor kurzem. Ist aber falsch. Siehe Beitrag "Re: Unterschied zwischen int i; in while und vor while"
Stefan U. schrieb: > Das dachte ich auch bis vor kurzem. Ist aber falsch. falsch, da ging es nicht um static. static wird wirklich nur einmal initialisiert und liegt auch nicht auf dem Stack sondern auf dem Heap.
> static wird wirklich nur einmal initialisiert
Und wird in "modbus.c" in der Prüfsummenberechnung als temporäre
Variable für das Ergebnis benutz. Und wird nur einmal mit 0
initialisiert.
Es stellen sich bei dem Programm also noch keine Optimierungfragen, denn
noch funktioniert es nicht.
Sollte es inzwischen doch funktionieren, weil der TO die "static"-Orgien
entfernt hat, so sollte er verstehen wollen, warum das jetzt tut. Sonst
setzt sich neben der bekannten "Regel", "viel volatile hilft viel", auch
noch die neue Regel, "mach dad static weg", zur Fehlerbehandlung durch.
Das ist Woodoo-Programmierung.
Carl D. schrieb: > Es stellen sich bei dem Programm also noch keine Optimierungfragen, denn > noch funktioniert es nicht. > Sollte es inzwischen doch funktionieren, weil der TO die "static"-Orgien > entfernt hat, so sollte er verstehen wollen, warum das jetzt tut. Sonst > setzt sich neben der bekannten "Regel", "viel volatile hilft viel", auch > noch die neue Regel, "mach dad static weg", zur Fehlerbehandlung durch. > Das ist Woodoo-Programmierung. Erstaunlicherweise funktionierte es oft aber nicht immer. Von ca. 100 Messungen kamen ca. 90% beim Master an. Es kann durchaus sein, dass es immer dann klappte, wenn die Prüfsumme zufällig korrekt war. Manchmal kamen leider keine Messwerte an und manchmal betrug die gesendete Temperatur 250 °C ... :-/ Wie dem auch sei. Ich werde es mir, sobald es meine Zeit zulässt, noch mal im Detail ansehen. Und Ja ich möchte sinnvoll programmieren und halte nichts von Vodoo - weder in der Software, noch in der Hardware. Bis dahin vielen Dank an alle, die sich an der Diskussion beteiligt haben! Viele Grüße, Alex P.S.: Uwe S. schrieb: > ich habe schon die Uart Interruput Routinen für TX und RX gesucht und > sie nicht direkt gefunden. > Und im File Modbus.c sind sie. Hältst du es für sinnvoller sie in uart.c unterzubringen? Dann müssen in uart.c aber die modbus-Variablen bekannt sein. Oder ich müsste mir noch mal Gedanken zur Schnittstelle machen...
:
Bearbeitet durch User
Carl D. schrieb: > auch > noch die neue Regel, "mach dad static weg", zur Fehlerbehandlung durch. > Das ist Woodoo-Programmierung. Ja und nein. Klar, das static will man hier erst mal nicht im Sinne des Erfinders haben. Auf der anderen Seite kann es sinnvoll sein, auch lokale Variablen static zu machen, weil sie dann in der SRAM Statistik auftauchen, was gerade bei kleinen Prozessoren nicht ganz uninteressant ist. Das man dann sich natürlich nicht auf die Intialisierung verlassen kann, ist selbstredend und folgt aus der eigentlichen Bedeutung von 'static'. Man verschwendet zwar ein paar Bytes, weiss aber exakt wieviele. Dem gegenüber steht, dass der Compiler in solchen Funktionen
1 | void modbus_convRxFrmToByteArray(uint8_t *modbusRxFrmBuffer) |
2 | {
|
3 | static uint8_t Digit; |
4 | static uint8_t c, i; |
5 | |
6 | for(i=1;i<(MODBUSRXFRMLENGTH-2);i++){ |
7 | c = *(modbusRxFrmBuffer+i); |
8 | if (c >= '0' && c <= '9') |
9 | Digit = (uint8_t) (c - '0'); |
10 | else if (c >= 'a' && c <= 'f') |
11 | Digit = (uint8_t) (c - 'a') + 10; |
12 | else if (c >= 'A' && c <= 'F') |
13 | Digit = (uint8_t) (c - 'A') + 10; |
14 | else
|
15 | break; |
16 | |
17 | *(modbusRxFrmBuffer+i) = Digit; |
18 | }
|
19 | |
20 | return; |
21 | }
|
die lokalen Variablen sehr wahrscheinlich allesamt in Registern halten kann, wodurch sie zur Laufzeit überhaupt keinen SRAM Speicher benötigen würden.
:
Bearbeitet durch User
1 | void modbus_convFrmByteToASCII(char *destiny, uint8_t val){ |
2 | const char hex_lookup[] = "0123456789ABCDEF"; |
3 | |
4 | destiny[1] = hex_lookup[val & 0x0F]; |
5 | destiny[0] = hex_lookup[(val>>4) & 0x0F]; |
6 | |
7 | return; |
8 | }
|
Beim gcc bringt dir das 'const' hier genau gar nichts. OK. Du kriegst hier einen Schönheitspreis. Dein Problem ist das SRAM und das wird ohne und mit const genau gleich benutzt. Wenn du dir diese 16, auf deinem Tiny kostbaren Bytes aus dem SRAM freischaufeln willst, dann musst das Array als __flash markieren oder bei einem älteren gcc den Weg über PROGMEM und die pgm_readxxx Funktionen gehen. Du zahlst dafür einen kleinen Preis in Form von ein paar Takzyklen aber ansonsten hat das keine Nachteile. Ausser natürlich, dass du 16 Bytes mehr SRAM zur Verfügung hast. https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read
:
Bearbeitet durch User
@khb Wenn ich ein Problem mit der RAM-Größe habe, dann wird das nicht besser, wenn ich für den lokalen Speicher aller Funktionen vorab RAM reserviere. Den kann der Compiler nämlich nicht so einfach wegoptimieren, der könnte ja tatsächlich bis zum nächsten Aufruf weiterleben müssen. Wegoptimieren kann er die nur, wenn sie vor der ersten Verwendung immer initialisiert wird. Aber genau das kann man dabei ja leicht falsch machen. Es kann sogar sein, das der Code dank "LD Rn,Y+idx" kürzer wird, wenn lokale Variablen, falls keine Register frei sind, im Stackframe liegen. Viel einfacher spart man RAM tatsächlich, wenn man die AVR/const/Flash-Problematik angeht. Und neuere GCC-Versionen machen es (in C) ja leicht Dank "__flash". Wenn man die Sourcen anschaut, dann sieht man, daß der Schreiber nicht orginär aus der AVR-Welt kommt: //Clock System Initialization klingt nach MSP430, da hat man einen linearen Addressraum und der Compiler muß nicht mit "named address space" belästigt werden.
Carl D. schrieb: > @khb > Wenn ich ein Problem mit der RAM-Größe habe, dann wird das nicht besser, > wenn ich für den lokalen Speicher aller Funktionen vorab RAM reserviere. Natürlich nicht. Aber ich kann wenigstens in der SRAM Statistik sehen, dass ich ein Problem haben werde. Das kann hilfreich sein. Darauf wollte ich hinaus. Ein größeres Problem von dem ich weiß kann (muss nicht) mir lieber sein, als ein kleineres von dem ich nichts weiß.
:
Bearbeitet durch User
Ein Compiler für einen AVR erzeugt den besten Code, wenn man möglichst wenig Variablen als "static" oder global nutzt. Am effizientesten kann der AVR nämlich mit lokalen non-static Variablen umgehen, sofern es keine Arrays sondern Basistypen sind (char, int, long, ...). Lokale Variablen sollten nur dann "static" sein, wenn ihr Inhalt über die Aufrufe hinaus erhalten bleiben muss. Andernfalls kosten sie nur Platz und Zeit. Es spart auch keinen Platz, mehrfach verwendete Schleifenzähler "i" ausserhalb der Funktion zu definieren, ganz im Gegenteil. Wenn du nicht wirklich weisst was du tust, dann versuch nicht, die Arbeit des Compilers zu übernehmen und im Quellcode unnötig zu optimieren. Ganz besonders nicht, wenn du dabei Regeln folgst, die zumindest beim verwendeten Prozessor ein Schuss in den Ofen sind.
:
Bearbeitet durch User
Dazu bräuchte es etwas, an das ich mich dunkel zu erinnern glaube, es schon mal gesehen zu haben: eine Statistik der Stackbekegung, das geht natürlich nur für nicht-rekursive Aufrufe, aber die Meldung "Achtung Rekursion" wäre ja als Warnung auch ganz gut. Jede Funktion hat Bedarf an Stack für ihren Aufruf, das Register-Sichern und eine Stackframe mit lokalen Daten. Der Compiler kennt den. Und auch die Aufrufreihenfolge. Wie geschrieben: ich hab schon Listings gesehen, wo so was mit draufstand. Ich meine es wäre PLMxyz gewesen.
Peter II schrieb: > static wird wirklich nur einmal initialisiert und liegt auch nicht auf > dem Stack sondern auf dem Heap. Als Heap bezeichnet man nur den Speicher für explizit dynamisch allozierte Daten, via malloc/calloc. Globale Variablen wie auch alle "static" Variablen liegen nicht auf dem Heap, sondern einträchtig nebeneinander in zwei festen Daten-Sektionen. Eine für explizit initialisierte Daten und eine für implizit beim Start genullte Daten. Der Unterschied ist nur, ob diese Variablen im gesamten Programm, nur im File oder nur in der Funktion bekannt sind. Globals/statics explizit mit 0 zu initialisieren kann je nach Compiler unnötig Platz im ROM verbrauchen, nämlich für jene 0, mit der die Variable ohnehin initialisiert würde.
:
Bearbeitet durch User
Hallo zusammen! Es freut mich, dass ich eine so angeregte Diskussion angestoßen habe. Ich habe versucht die hier gegebenen Vorschläge umzusetzen. Insbesondere habe ich ein Update des AVR-GCC gemacht (war 4.3.3, ist jetzt 4.8.1). Das Ergebnis: Program Memory Usage : 1940 bytes 94,7 % Full Data Memory Usage : 56 bytes 43,8 % Full EEPROM Memory Usage : 1 bytes 0,8 % Full Insbesondere der RAM ist nun also leerer. Ich habe jetzt auch Konstanten mit "__flash" angelegt. Ich werde über Nacht den Sensor (Modbus-Slave) wieder messen lassen, um die "Stabilität" zu beobachten. Carl D. schrieb: > //Clock System Initialization > klingt nach MSP430 Ich arbeite zumeist mit Freescale HCS08- und HCS12X- MCUs. Uwe S. schrieb: > ich habe schon die Uart Interruput Routinen für TX und RX gesucht und > sie nicht direkt gefunden. > Und im File Modbus.c sind sie. Wie könnte man das geschickter anordnen? Zum TX-Interrupt: Ich möchte den Driver möglichst schnell nach Senden des letzten Zeichens deaktivieren (da halb-duplex-Betrieb). Zum RX-Interrupt: Da werden die Zeichen zu einem String zusammengepackt und wenn der String fertig ist ("\r\n") wird ein Flag gesetzt. Das Problem der UART weiß ja nichts davon, dass er das "modbus-Protokoll" bedienen soll... Für Vorschläge bin ich jederzeit offen. Viele Grüße, Alex
Alex B. schrieb: > Ich arbeite zumeist mit Freescale HCS08- und HCS12X- MCUs. Die haben keine für lokale Variablen geeigneten Register, weshalb alle nicht sowieso vom Compiler wegoptimierten Variablen unweigerlich im RAM landen, egal ob global oder lokal, ob static oder auto. Bei den AVRs mit 32 Registern ist das anders. Regeln, die man sich für die Freescales angewöhnt haben mag, sind auf AVRs oft nicht anwendbar.
:
Bearbeitet durch User
> Die haben keine für lokale Variablen geeigneten Register, weshalb alle
nicht sowieso vom Compiler wegoptimierten Variablen unweigerlich im RAM
landen, egal ob global oder lokal, ob static oder auto.
Aber auch für den Fall gibt es den fiesen Unterschied ob ich static in
der Deklaration oder erst später initialisiere. Also hinschreiben, was
man meint. Legt der Compiler für die Freescale Dinger auto Variablen
dann auf den Stack, oder haben die wirklich fixe Adressen? Kann der dann
ohne Spezial-Keyword Reentrante Funktionen? Ich denke da an 51er
Compiler.
BTW, "auto" (ja, ich hab's selbst benutzt) hat in neusten C++-Versionen
eine geänderte Bedeutung. Nicht die Speicherklasse, "nicht static/nicht
register" sonder der Typ wird aus dem Umfeld ermittelt. Man hat diese
Inkompatible Änderung wohl deshalb gemacht, weil auto das "nie benutzte"
Keyword ist.
Carl D. schrieb: > Legt der Compiler für die Freescale Dinger auto Variablen > dann auf den Stack, oder haben die wirklich fixe Adressen? Da diese Prozessoren relativ zu Stackpointer adressieren können werden "auto" Vars wohl auf dem Stack landen. Neben Zirkus mit Reentrancy und Int-Handlern erspart das dem Compiler die Optimierung nie gleichzeitig genutzter Variablen auf die gleichen Adressen. Etwas, was für 8051 und PIC (12/14bit) Compiler wichtig ist. Ein Stack macht das automatisch - ist aber, wie oben schon erwähnt, schlechter kalkulierbar. Letztlich bringt es auch bei diesen Prozessoren sicherlich nicht viel, nur lokal genutzte Variablen global/statisch zu definieren. Zumal man dem Compiler die Optimierung erschwert. Der Compiler ist (hoffentlich) für den üblichen C Stil gebaut. Nur macht es im Code der Freescales keinen grossen Unterschied aus, ob die Daten mit 8 Bit Offset relativ zu SP adressiert werden, oder mit fester 8 Bit Adresse (wenn wenig Daten). Hingegen ist der Unterschied zwischen Register und RAM beim AVR sehr gross. Ich wäre aber nicht erstaunt, im Kontext der Freescales Tipps zu finden, dass häufig genutzte Daten mit direkter 8-Bit Adresse besser sind als lokale. Denn 8-Bit relativ zu SP ist einen Takt langsamer ('08). Für die 12er gibts übrigens eine GCC Implementierung. Wobei GCC für Akku-Architekturen alles andere als ideal ist. Darin finden sich einige Pseudo-Register im RAM. GCC wird vorgegaukelt, als hätte der einige Register. Auch in einer Version für die an Register etwas knappen Renesas R8C/M16C fand ich diese Technik.
:
Bearbeitet durch User
Wenn so ein Compiler das Overlay-en von Daten beherscht, dann hat er auch wesentliche Informationen, die zur Berechnung der notwendigen Stack-Tiefe gebraucht werden. Auch daß er das Ende einer Rekursion nicht kennt, könnte er sagen. Dann müßte Informationsbedarf nicht zu falschen Programmierweises führen. "static" weils dann in .data Segment ausgewiesen wird. (das ist so wie der BWLer, dem Kosten egal sind, solange sie nicht an der falschen Stelle in der Bilanz auftauchen. "Extern sind keine Bösen Personalkosten".)
Carl D. schrieb: > Wenn so ein Compiler das Overlay-en von Daten beherscht, dann hat er > auch wesentliche Informationen, die zur Berechnung der notwendigen > Stack-Tiefe gebraucht werden. So herum schon. Aber nicht unbedingt anders herum. Ein Compiler, der Autos auf den Stack legt und somit keine RAM-Overlays braucht, der macht sich evtl. nicht diese Mühe. Zumal GCC nicht primär für Embedded entwickelt wird, und bei PCs interessiert das kein Schwein.
:
Bearbeitet durch User
> falsch, da ging es nicht um static.
Ach ja, Asche auf mein Haupt.
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.