Forum: Compiler & IDEs Variable an bestimmter Adresse


von Rolf Magnus (Gast)


Lesenswert?

Ich weiß, daß man normalerweise dem Compiler/Linker die Anordnung der
Variablen im Speicher überlässt, aber es gibt ja z.B. die Konvention,
in die oberste EEPROM-Stelle den Wert zu schreiben, der ins
OSCCAL-Register geladen werden soll. Das hätt ich nun gern als Variable
in meinen C-Code geschrieben.
Kann ich dem Compiler irgendwie sagen, daß er diese spezielle Variable
ans Ende des EEPROM stecken soll?

von Rolf Magnus (Gast)


Lesenswert?

Bedeutet das Fehlen einer Antwort, daß es nicht geht, oder daß keiner
weiß, wie es geht?

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

du könntest die Variable in eine eigene Sektion packen und diese dann
beim Linken an eine bestimmte Addresse verschieben und dann mit
avr-objcopy aus dem Binary rausfummeln (evtl. zusammen mit den anderen
EEPROM Variablen). Das sollte eigentlich funktionieren. Aber Jörg hat
da sicher eine einfachere Idee :-)

Matthias

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Aber Jörg hat
> da sicher eine einfachere Idee :-)

Harhar. :)

Naja, wenn's eine feste Adresse sein soll und man den Kram
ohnehin mit eeprom_read_foo() lesen muss, warum den Pointer
nicht gleich über E2END (aus <avr/io.h>) berechnen?

von Rolf Magnus (Gast)


Lesenswert?

Ich wollt's halt als Variable im C-Code haben, so daß ich da direkt den
Wert angeben kann und er automatisch im eeprom-hex-File landent, statt
dieses eine Byte immer nachträglich einzeln von Hand ändern zu müssen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hmm, du willst den OSCCAL-Wert im C-File festlegen?  Das verstehe
ich nicht so recht.

Wenn du nur einen Vorgabewert haben willst, kannst du doch einfach
nachsehen, ob die Speicherstelle noch 0xFF hat und in diesem
Falle OSCCAL belassen, wie es ist.

von Rolf Magnus (Gast)


Lesenswert?

> Hmm, du willst den OSCCAL-Wert im C-File festlegen?

Genau.

> Das verstehe ich nicht so recht.

Naja, wenn ich eine µC-Schaltung bastle und programmiere, verwende ich
normalerweise immer denselben µC und wechsle sie nicht ständig durch.
Also habe ich auch immer denselben OSCCAL-Wert (bis ich halt den µC aus
Dämlichkeit kapputgemacht hab). Und damit ich nicht jedes Mal nach dem
Programmieren den OSCCAL-Wert nochmal extra schreiben muß, möchte ich,
daß er gleich im C-Code und daduch auch nachher im hex-File steht.
Falls ich mal einen anderen (oder mehrere) µC programmieren will, weil
die Schaltung mehrmals aufgebaut wird, könnte ich dann immer noch für
jeden einzeln den Wert für OSCCAL an die richtige Stelle schreiben,
weil sie immer am Ende des EEPROM ist und ich nicht abhängig von der
Software-Version die Adresse erst raussuchen muß. Klingt das so
unsinnig?

> Wenn du nur einen Vorgabewert haben willst, kannst du doch einfach
> nachsehen, ob die Speicherstelle noch 0xFF hat und in diesem
> Falle OSCCAL belassen, wie es ist.

Belassen kann ich es nicht bei z.B. einem Mega8, den ich mit dem
internen 8-Mhz-RC-Oszillator takten will, weil der für 1, 2, 4 und 8
Mhz jeweils einen eigenen RC-Oszillator mit eigenem OSCCAL-Wert hat und
immer der für 1 Mhz vorgeladen wird.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hmm, warum willst du den aber immer wieder neu beschreiben und
nicht einfach nur einmal?  (EESAVE-Fuse setzen.)

von Stefan K. (_sk_)


Lesenswert?

Du musst dafür eine neue Sektion im EEPROM anlegen. Ändern musst Du
dafür:

im Makefile (letzte Zeile neu + Backslash vorletzte Zeile):

COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000 \
--change-section-address .eetest-0x820000

%.eep: %.elf
  @echo
  @echo $(MSG_EEPROM) $@
  -$(OBJCOPY) -j .eeprom -j .eetest \
      --set-section-flags=.eeprom="alloc,load" \
  --change-section-lma .eeprom=0 \
      --change-section-lma .eetest=100 -O $(FORMAT) $< $@

In Deinem Sourcecode:

uint8_t  eeprom_test  _attribute_ ((section (".eetest"))) = 0xAA;
uint8_t  eeprom_dummy _attribute_ ((section (".eeprom"))) = 0x80;


Ich gehe von dem Beispiel-Makefile der WINAVR-Distribution aus.
Die neue Sektion eetest beginnt in diesem Beispiel ab der Adresse
100(hex)
(einstellbar im objcopy-Kommando --change-section-lma .eetest=100).

Falls Du das elf-File mit AVRStudio verwendest: das hatt (bei mir)
früher Probleme mit neuen Sektionen. Ob das in der mittlerweile neueren
Version anders ist, habe ich noch nicht ausprobiert.

Gruß, Stefan

von Peter (Gast)


Lesenswert?

Warum nicht einfach eine EEPROM-Adresse so definieren

#define MyCalVal (u08*)E2END   // Pointer auf's letzte Byte im EEPROM
.
.
.
if (eeprom_read_byte(MyCalVal)==0xFF)
{
 eeprom_write_byte(MyCalVal,MyDefaultConst)
}
.
.
.
OSCCAL=eeprom_read_byte(MyCalVal);   // Get Calibration Value
.

von Stefan K. (_sk_)


Lesenswert?

@Peter:

Das geht natürlich auch, vor allem für diesen speziellen Fall, wo nur
eine Variable benötigt wird. Allerdings sollte man beachten, dass der
Compiler dabei keinen Speicher für eine Variable belegt, d.h. man ist
selbst für das Speichermanagement verantwortlich (nicht wirklich ein
Problem, wenn es nur eine Variable am Ende des EEPROMs ist).

Gruß, Stefan

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.