Wenn ich in C vor eine Variable "const" schreibe bedeutet das ja, dass diese nicht verändert werden darf/kann (wird quasi zu einer Konstanten). Wenn ich das bei der uC-Programmierung mache, so habe ich gehört, packt der Compiler diese Konstante in den Flash. Ist richtig? Mein Compiler von GNU für Arm-Prozessoren (arbeite mit dem LPC1768) macht es, bei einigen aber nicht bei allen. Warum? Kann ich das irgendwie beeinflussen?
R. B. schrieb: > Wenn ich in C vor eine Variable "const" schreibe bedeutet das ja, dass > diese nicht verändert werden darf/kann (wird quasi zu einer Konstanten). > Wenn ich das bei der uC-Programmierung mache, so habe ich gehört, packt > der Compiler diese Konstante in den Flash. Ist richtig? Kommt auf den Compiler an. Kann man so nicht allgemein sagen. Näheres weiß die Doku zu deinem Compiler. > Warum? Weil C eine genormte Sprache ist, die vom µC bis zum Grossrechner mit seinem genormten Teilen überall gleich funktioniert. Und die ISO-Norm hat zum Thema Flash nichts zu sagen, weil sie nicht davon ausgehen kann, dass JEDER Computer über ein Flash verfügt. Daher obliegt das deinem Compilerbauer, die Freiheiten, die ihm die Norm lässt, in der jeweiligen Situation auszunutzen bzw. sinnvoll einzusetzen. Und für den einen bedeutet das eben "const kommt ins Flash" und für den anderen bedeutet es das nicht. Die Norm beschreibt lediglich, wie sich das Programm bei Verwendung des Schlüsselwortes 'const' zu verhalten hat, aber nicht wie das zu implementieren ist.
const ist eigentlich nur dazu da, dass der Compiler ne Warnung ausgibt wenne doch mal schreibend darauf zugreifst. Wie bereits gemerkt, wirds unterschiedlich behandelt. Beim AVR-GCC zB muss man noch PROGMEM dahinter schreiben. -> Also mal in der Doku gucken.
Martin Wende schrieb: > Beim AVR-GCC zB muss man noch PROGMEM dahinter schreiben. Das ist eine Spezialität, die der Harvard-Architektur des AVR geschuldet ist. Normale von-Neumann-Systeme brauchen so etwas nicht (und entsprechend auch nicht die progmem.h-Klimmzüge).
Rufus Τ. Firefly schrieb: > Normale von-Neumann-Systeme brauchen so etwas nicht Weißt du denn, wie es dann gehen könnte? Also ich möchte gern dem Compiler überlassen wohin er es in den Flash schreibt.
Martin Wende schrieb: > const ist eigentlich nur dazu da, dass der Compiler ne Warnung ausgibt > wenne doch mal schreibend darauf zugreifst. käse. http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#Function-Attributes
R. B. schrieb: > Weißt du denn, wie es dann gehen könnte? Also ich möchte gern dem > Compiler überlassen wohin er es in den Flash schreibt. Poste doch mal ein Beispiel, wann eine const-Variable (auf deiner Maschine) nicht im Flash landet.
1 | typedef const struct{ |
2 | char sms_sent[100]; |
3 | }log_file_t; |
4 | |
5 | const log_file_t log_file; |
Probier mal typedef const struct{ const char sms_sent[100]; }log_file_t; Mit Deiner Definition sagst Du nur, das der Pointer nihct beschrieben werden darf...
Es kann Sinn machen, const Variable nicht ins Flash zu schreiben: µCs mit einer sehr hohen CPU Frequenz können nicht mit voller Geschwindigkeit aus dem Flash lesen sondern verlangsamen den Zugriff durch Waitstates. Eine Const-Variable im RAM kann dagegen ohne Waitstates gelesen werden.
R. B. schrieb: > Mein Compiler von GNU für Arm-Prozessoren (arbeite mit dem LPC1768) > macht es, bei einigen aber nicht bei allen. Warum? Kann ich das > irgendwie beeinflussen? Kann damit zusammenhängen, daß manche CPUs bei Datenzugriffen schneller im RAM arbeiten als im Flash. Beim TriCore ist es so, daß Datenzugriffe ins Flash deutlich mehr Zyklen brauchen als ins RAM, daher wird der TriCore schneller, wenn Konstanten im RAM liegen. Vorausgesetzt es ist genug RAM vorhanden. Wie's bei Deinem ARM ist, weiß ich nicht.
Man kann es ja einfach ausprobieren mit einem simplen "const" und dann im erzeugten memory map (evtl. *.map) nachschauen, wo die Konstante hingelegt wird.
R. B. schrieb: > Rufus Τ. Firefly schrieb: >> Normale von-Neumann-Systeme brauchen so etwas nicht > > Weißt du denn, wie es dann gehen könnte? Also ich möchte gern dem > Compiler überlassen wohin er es in den Flash schreibt. Na dann überlass es dem Compiler :-) mit const i = 3; wird er i nach .rodata legen, zumindest bei ELF Targets, und die Implementierung wird .rodata in den Flash lokatieren, wenn das praktikabel ist. Ausnahmen bei GCC ist const volatile, das per Default nicht nach .rodata gelegt wird, wo es aber je nach Anwendung hingehört.
Das Problem ist gelöst! Der Compiler mochte es anscheinend nicht, wenn bei der Definition der Konstanten kein Wert festgelegt wurde. Also so läuft es jetzt bei mir:
1 | typedef const struct{ |
2 | const char sms_sent[100]; |
3 | }log_file_t; |
4 | |
5 | const log_file_t log_file={{'\0'}}; |
R. B. schrieb: > Also so läuft es jetzt bei mir: Und welchen Sinn hat eine Konstante mit diesem Inhalt? Ist ja nicht so, daß Du diese Konstante ohne größeren Aufwand zur Laufzeit ändern könntest, ist schließlich 'ne Konstante. Was hast Du damit vor?
Rufus Τ. Firefly schrieb: > Was hast Du damit vor? Also im Prinzip möchte ich damit Speicherplatz auf dem Flash reservieren um später mit einer CopyRAMToFlash-Fkt. darauf zu schreiben und den mit dem Namen ansprechen zu können. Vorher war es zum teil so, dass der Compiler etwas auf den Flash gelegt hat und ich über direkte Addressierung ebenfalls. Fand ich aber keine saubere Lösung und so (hoffe ich) entscheidet der Compiler wo er was hinlegt.
Hmm. Naja, das kann man dann tatsächlich so machen. Allerdings hast Du dann keine Kontrolle darüber, wo im Flash das so erzeugte Objekt liegt, und ob es beispielsweise über eine Grenze zwischen zwei Flash-Segmente hinausreicht, was beim Beschreiben wiederum zu Problemen bzw. Mehraufwand führt.
Rufus Τ. Firefly schrieb: > Allerdings hast Du dann keine Kontrolle darüber, wo im Flash das so > erzeugte Objekt liegt, Brauche ich doch nicht, solange ich es über den Namen ansprechen kann. >ob es beispielsweise über eine Grenze zwischen zwei Flash-Segmente hinausreicht, >was beim Beschreiben wiederum zu Problemen bzw. Mehraufwand führt. Auf dieses Problem bin ich gerade gestoßen... :-/
Ich würde die letzte(n) Page(s) für sowas nutzen. Du musst dann halt nur drauf achten, dass deine Speicherbelegung durch das reguläre Programm nicht größer wird als bis dahin.
Vielleicht kann man dem Compiler ja sagen, welchen Bereich im Flash er nutzen darf und welchen nicht. Die Lösung mit der Null-Konstante ist imo Murks, zumal ja nicht mal garantiert ist, dass der Compiler die Konstante in den Flash legt. Er könnte sie sogar wegoptimieren. Da müssten dann schon noch Attribute dazu, die das Anlegen im Flash erzwingen. Wenn man aber eh am Compiler vorbei auf den Flash zugreift, kann man auch den Ort selber festlegen.
Hm... Wieso sollte man das so im Flash ablegen wollen? Wenn du für den Prototypen keinen Platz hergeben willst, initalisier ihn als Pointer mit Array-Größe 0 und hol dir dann den Platz, den du wirklich brauchst mit einem malloc. Oder wenn du Daten aus dem Flash holen willst, legst du einen Pointer auf die Struktur an, dessen Startadresse im Flash liegt und springst dann jeweils um eine Struktur-Größe weiter. Du musst dir dann nur noch hinterlegen, wie viele Sätze du im Flash liegen hast.
Mittels des Linker-Scripts kann man angeben welche Teile wo landen sollen. Auch wird dort angegeben welche RAM und Flash Bereiche es gibt. So könnte man das vorhandene Flash im Linker Script dann einfach aufteilen in zwei Sektionen. Den zweiten Bereich verwendet man dann eben für diese Daten. Dadurch lässt sich genau festlegen an welcher Adresse dieser Bereich liegt. Einfach mal die Doku zum Gnu ld ansehen, und in das vorhandene Linker-Script des eigene Projektes schauen. So müsste z.B. eine MEMORY Definition dort sein. Hier mal ein Beispiel: MEMORY { ram : ORIGIN = 0x40000000, LENGTH = 64K flash : ORIGIN = 0x80000000, LENGTH = 1M } Nun könnte man "flash" aufteilen: MEMORY { ram : ORIGIN = 0x40000000, LENGTH = 64K flash : ORIGIN = 0x80000000, LENGTH = 1000K sms : ORIGIN = 0x800FA000, LENGTH = 24K } Unter SECTIONS könnte man dann z.B.: .sms_data : { *(.text.sms_data) } >sms . = ALIGN(4); Dies sagt dem Linker das die Sachen mit dem Attribut "sms_data" dann im MEMORY Bereich mit dem Namen "sms" liegen. Eigentlich könnte man dann über: typedef const struct { const char sms_sent[100]; } log_file_t; const log_file_t log_file _attribute_ ((section ("sms_data"))); dem Compiler/Linker sagen das es dann auch in diese Sektion gelegt werden soll. Siehe auch: http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Variable-Attributes.html Somit hat man den Bereich dann sauber festgelegt. Mittels der Änderungen im Linker-Script wird es immer an der gleichen Adresse platziert, und da der Bereich dort auch explizit nur für sms_data ausgewiesen ist wird dort auch kein Programcode abgelegt. Grüße, Chris Grüße, Chris
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.