Flash und "const"

OP #2918990
Lesenswert?

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?
#2918994
Lesenswert?

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.
Gast #2919081
Lesenswert?

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.
Gast #2919083
Lesenswert?

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.
Persönliche Seite #2919181
Lesenswert?

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.
OP #2922533
Lesenswert?

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'}};
OP #2922550
Lesenswert?

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.
OP #2922561
Lesenswert?

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... :-/
Gast #2922656
Lesenswert?

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.
#2923930
Lesenswert?

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.
(Firma: Atelier Klippel) #2923955
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren