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?
> 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.
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.
"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
Ä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?
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)
Konkret geht es um die in Main.h definierten Pointer, bei Zeile 41 geht die Beschreibung los (mit Hinweis darauf, dass RAMEND runtergesetzt wird)
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, ...)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.