Forum: Compiler & IDEs Variablen vs. Speicheradressen


von Christian O. (derbrain)


Lesenswert?

Hallo,
ich hab jetzt mal Beispielcode von Atmel durchgeackert, und dabei ist
mir aufgefallen, dass dort sowohl globale Variablen als auch direkte
Speicheradressen verwendet werden. Was für einen Sinn hat es, die
Adressen explizit anzugeben?
Ich nehme an, volatile wird dabei überflüssig (wird auch niemals
verwendet). Aber hat es auch andere Vorteile?

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


Lesenswert?

> Was für einen Sinn hat es, die Adressen explizit anzugeben?

Das kann man nur mit dem Kontext entscheiden.  Man könnte zum Beispiel
den externen Speicher ,,mit der Hand'' verplanen, und den internen
RAM
dem Compiler für Variablen und Stack überlassen.

Man könnte externe Geräte über memory-mapped IO einbinden, dann hat
man auch feste Adressen.  Letztlich sind bei AVR-GCC/avr-libc alle
IO-Register auf diese Weise eingebunden, d. h. sie lösen alle auf eine
feste Adresse auf (die ja im Datenblatt steht).  Da alle IO-Register
über MMIO (memory-mapped IO, also über die STS/LDS-Befehle) erreichbar
sind, hat man so einen garantierten Weg.  Manche davon sind auch via
IN/OUT erreichbar und bei wiederum einem Teil lassen sich SBI und CBI
für die Bitmanipulation benutzen.  Es obliegt dann dem optimizer, das
entsprechend zu ersetzen.

> Ich nehme an, volatile wird dabei überflüssig (wird auch niemals
> verwendet).

Überhaupt nicht.  Für den Compiler ist und bleibt das ein Pointer.
Wenn man sichergestellt haben will, dass der entsprechende Inhalt auch
wirklich mit jeder Zuweisung im C-Programm zurückgeschrieben wird
bzw. jedes Lesen im C-Programm tatsächlich von der entsprechenden
Speicherstelle gelesen wird (bei MMIO will man das wohl immer), dann
muss man den volatile deklarieren.  Exakt so funktionieren auch die
IO-Makros (also PORTB usw.).

Dass der IAR (auf dem der meiste Atmel-Beispiel-Code aufsetzt) hier
anders optimiert und dadurch das volatile nicht unbedingt braucht, ist
letztlich Zufall.

von Christian O. (derbrain)


Lesenswert?

Danke für die ausführliche Antwort :-)

Das mit den externen Geräten leuchtet mir ein, aber was ist der Sinn im
"normalen" Gebrauch?
Im Beispielprogramm werden werden normale globale Variablen nur
innerhalb einer Datei verwendet (im Header-File nicht vorhanden),
während die Speicher-Pointer allgemein sichtbar sind. Konkret sind das
Datum, Uhrzeit und Temperatur. Externer Speicher wird nicht verwendet,
RAMEND muss extra runtergesetzt werden damit die Speicherstellen nicht
überschrieben werden. Da also schon einiges an Aufwand dahintersteckt,
dachte ich mir, das muss einen tieferen Sinn haben. Auch möglich, dass
das nur verwendet wird um zu zeigen wie so was geht (weil
Beispielsoftware).

@ volatile: Ich habs mir nochmal genauer angeschaut, dass die das nicht
verwenden liegt wohl wirklich am anders optimierenden Compiler, sonst
würde das Programm kaum laufen.

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


Lesenswert?

Nö, kein Gefühl, warum das dort so gemacht worden ist.

von peter dannegger (Gast)


Lesenswert?

"Im Beispielprogramm..."

Welches ?

Wenn Du mal das Programm als Anhang oder nen Link darauf angibst, dann
könnte man vielleicht näheres dazu sagen.

Sonst ist das hier nur Rätsel raten.


RAMEND zu verbiegen klingt ja schon ziemlich krank.


Peter

von Christian O. (derbrain)


Angehängte Dateien:

Lesenswert?

Ähm, sorry, das hätt ich auch gleich machen können... :-)

Der Code ist im Anhang, eine Beschreibung was das ist gibts hier:
http://www.atmel.org/dyn/resources/prod_documents/doc2529.pdf

Da ist das Programm auch als Flussdiagramm dargestellt. Wie macht ihr
das eigentlich? Was ich so mitbekommen habe seid ihr so was wie
µC-Gurus ;-) Codet ihr gleich los oder wie geht ihr bei der Entwicklung
vor?

von Karl H. (kbuchegg)


Lesenswert?

So auf die Schnelle ist mir beim durchschauen des Codes
nichts aufgefallen. Worauf moechtest Du konkret hinaus?
(ala: Schau mal in Datei xyz, Zeile abc)

von Christian O. (derbrain)


Lesenswert?

Konkret geht es um die in Main.h definierten Pointer, bei Zeile 41 geht
die Beschreibung los (mit Hinweis darauf, dass RAMEND runtergesetzt
wird)

von Karl H. (kbuchegg)


Lesenswert?

Der Autor wollte sicherstellen, dass die Variablen
tatsaechlich hintereinander und so wie er es moechte
im Speicher angeordnet werden.

Dadurch kann er in UART.C in den Funktionen
Send_TX_data bzw. Store_RX_data darauf wie
auf ein Array zugreifen.

            ...

            *(&HOUR + HEX_Cnt) = HEX_byte;

            ...

            Nr_ASCII_bytes = HEX2ASCII(*(&HOUR + Cnt++));

je nach Wert von HEX_Cnt bzw. Cnt wird dann in Wirklichkeit
eine der Variablen HOUR, MINUTE, SECOND, ...   genommen.

Ansonsten sehe ich keinen wirklichen Grund, warum das so gemacht
wurde. Und selbst wenn dies der einzige Grund ist, so gibt es
in C wesentlich bessere Moeglichkeiten sowas zu realisieren
(Stichworte: Reihenfolge und padding uber ein Array regeln.
Oder eine struct verwenden, dann muss man sich um das Padding
meist selbst kuemmern, ...)

von Christian O. (derbrain)


Lesenswert?

Nachdem der tägliche Server-Error mein Posting gefressen hat, versuch
ichs nochmal so gut es geht zu rekonstruieren:

Mein Ansatz wäre auch ein Array gewesen für das Datum. Vielleicht
wollten die nur zeigen, DASS sowas geht.
Oder es ist einfach eine seltsame Art zu Programmieren. Z.B. sieht die
Funktion HEX2ASCII nach ziemlichem Overhead aus. Wenn man davon
ausgeht, dass es nur für Temperaturen von 0 bis 20 Grad verwendet wird
(negativ geht gar nicht), hält es sich noch in Grenzen, aber was wäre
bei 180 Grad? Wäre so was nicht besser:

Dec_L = Hex % 10;
Hex = Hex / 10;
...

und das Ganze noch in einem Array statt drei Variablen? Oder kommt das
in Assembler aufs Gleiche raus?

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.