Forum: Mikrocontroller und Digitale Elektronik absolute Adressen in C?


von crazy horse (Gast)


Lesenswert?

Folgendes Problem: Ich möchte ne ganze Menge Kennlinien als Konstanten 
im Flash unterbringen, allerdings sollen die per download später 
verändert werden können.
Es sind exakt 43200Byte, den Rest der zu 64kB würde ich gerne unbenutzt 
lassen, da diese beim Blocklöschen (64kB) auch verloren gehen würden.
Das Feld beginnt bei 0xD0000, der Rest soll dann ab 0xE0000 beginnen 
(M16C62).
Im Moment behelfe ich mir mit:
const char dummy[0x5740];
Fragen: warum funktioniert folgendes nicht:
const char dummy[0x10000-3*3600*4];
//64k-3Felder a 3600 float-Werte zu je 4 Byte
Anfangsadresse für Rest der Konstanten wird vom Compiler (NC30) nicht 
wie erwartet zu 0xE0000 sondern zu 0xF0000 berechnet??
Wahrscheinlich werden später noch weitere Daten in die 64k kommen, so 
dass ich mir die ganze Bytezählerei gerne sparen würde.
Wie also kann man absolute Adressen festlegen?
const char version[]="...."; soll also in jedem Fall bei 0xE0000 
beginnnen.

von Karl H. (kbuchegg)


Lesenswert?

const char* Version = (const char*)0xE0000;

Damit hast du einen Pointer der auf die absoulte Adresse
0xE0000 zeigt. Benutzen kannst du den ganz normal, so wie
du auch das Array benutzt hättest.

von crazy horse (Gast)


Lesenswert?

ne, das hilft mir gar nichts. Es geht ja darum, dass die restlichen 
Konstanten wirklich erst ab 0xE0000 im Flash stehen und eben nicht schön 
platzsparend aneiander gepappt werden.
In Assembler würde das so aussehen:
.org 0xD0000
.db .....//7200 float-Werte

.org 0xE0000
der Rest

von Peter D. (peda)


Lesenswert?

Dafür gibt es keine generelle Antwort in C.

Es ist von Deinem speziellen Compiler abhängig.

Was sagt den Dein Compiler- und Linker-Manual dazu ?

Beim Keil C51 gibt es z.b. 2 Wege.
Man kann im Source-File ein Variablen-Array an einer bestimmten Adresse 
anlegen (at) oder dem Linker angeben, daß er ein Objekt an eine 
bestimmte Adresse linken soll.
Ich benutze das z.B., um einen Gerätestring immer an 0x0100 zu linken. 
Damit weiß ich immer, wozu ein Hex-File gehört.


Peter

von crazy horse (Gast)


Lesenswert?

ok, habe ich mir schon gedacht.
Ich werde mich vielleicht später nochmal damit beschäftigen, im Moment 
bleibts dann erstmal bei den dummy-Daten.
Bleibt die Frage, warum das nicht funktioniert:
const char dummy[0x10000-3*3600*4];
sollte eigentlich ein Array alegen, dass die restlichen Bytes bis zur 
64k-Grenze verbrät. Vertut aber 0x15740 Bytes statt 0x5740. Mach ich da 
einen Denkfehler oder spinnt der Compiler?

von eProfi (Gast)


Lesenswert?

Verstehe, Du möchtest, dass der Compiler die Größe des Dummy-Feldes 
automatisch berechnet, und alle weiteren Variablen (nicht nur 
einzelne)danach anordnet.
Evtl. hilft es, mit  sizeof  die Größe der einzelnen chars und floats
und Array mal anzeigen zu lassen.

Was ich auch schon öfters hatte: Der Compiler rechnet Konstanten erstmal 
mit 16 Bits, außer man hängt ein L daran an.
Versuchs mal mit char dummy[65536L-3L*3600L*4L]

"Vertut aber 0x15740 Bytes statt 0x5740."
schon komisch, wenn dann hätte ich mir noch eher vorstellen können, dass 
er wg. Padding  2* 0x5700 reserviert.

Kannst Du mal hilfsweise das Dummy in zwei oder drei aufteilen und im 
Assembler nachschauen, was er wirklich macht, wohin er die arrays legt?

const char dummy1[8]=(0,1,2,3,4,5,6,7);
const char dummy2[0x57400-16];
const char dummy3[8]=(7,6,5,4,3,2,1,0);

von crazy horse (Gast)


Lesenswert?

Na, super :-)
Mit L klappte es wie gewünscht
habe es jetzt mit sizeof gelöst:
const char 
dummy[0x10000-sizeof(kennlinie1)-sizeof(kennlinie2)-sizeof(kennlinie3)];
passt :-)
Da wiederum brauch ich kein L.
Egal, vielen Dank

von Rolf Magnus (Gast)


Lesenswert?

> Was ich auch schon öfters hatte: Der Compiler rechnet Konstanten
> erstmal mit 16 Bits, außer man hängt ein L daran an.

Genauer gesagt sind Konstanten vom Typ int, wenn dieser Typ groß genug 
ist. Ich nehme mal an, daß int beim gegebenen Controller 16 Bit breit 
ist. Wenn bei einer Berechnung alle Operanden vom Typ int sind, ist es 
auch das Ergebnis. 65536 passt zwar nicht mehr und ist daher sowieso 
long, aber 3, 3600 und 4 nicht. Das Ergebnis der zuerst ausgeführten 
Multiplikation ist also vom Typ int, aber die 43200 passen nicht mehr da 
rein. Durch den Überlauf ergibt sich stattdessen ein Wert von -22336. 
Erst danach wird dann zur Subtration wegen der 65536 auf 32Bit 
erweitert. Die Größe des Blocks ist also nicht 65536-43200=22336 
(=0x5740), sondern 65536+22336=87872 (=0x15740)

> Versuchs mal mit char dummy[65536L-3L*3600L*4L]

Damit gehst du auf Nummer Sicher. Theoretisch würde es auch rechen, nur 
bei einer der letzten drei Zahlen das L anzuhängen, aber mit allen Ls 
ist der Code leichter verständlich.

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.