www.mikrocontroller.net

Forum: Compiler & IDEs Adresscodierung mit Pointer


Autor: müllo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir interessenhalber mal das Buch "Softwareentwicklung in C"
von Jörg Wiegelmann ausgeliehen und habe bei Kapitel 9.2 eine Frage.

Es geht dabei um Ansprechen von Hardwarebausteinen über Ihre Adresse
und dabei wird folgendes Beispiel gebracht:

-----------------------------------------------------------------
// Auszug Beispiel 9.10
char *z_reg = (char *)0x5513; //Def. Zeiger und Init mit Adresse
*z_reg = 44;                  //Laden des Wertes
-----------------------------------------------------------------

Ich habe ein Problem mit der Initialisierung der Zeile 1. Wieso wird
die Zuweisung mit dem cast-Operator gemacht? Würde eine direkte Angabe
der Adresse (siehe unten) nicht reichen?

-----------------------------------------------------------------
char *z_reg;                  //Definition
z = 0x5513;                   //Zuweisung Adresse
*z_reg = 44;                  //Laden des Wertes
-----------------------------------------------------------------

Viele Grüße
müllo

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil 0x5513 ein intergertyp ist, die zuweisung an einen zeiger/pointer
aber einen zeigertyp benötigt/erwartet.

Autor: müllo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also kann ich die Adresscodierung anstatt mit einem char-Pointer (wie im
Buch beschrieben) besser mit einem int-Pointer realisieren, oder???

-----------------------------------------------------------------
int *z_reg;                  //Definition
z = 0x5513;                   //Zuweisung Adresse
*z_reg = 44;                  //Laden des Wertes
-----------------------------------------------------------------

Oder wird der char-Pointer wegen des Speicherplatzes benutzt???

Viele Grüße
müllo

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

das kommt eben drauf an was an der Addresse angeschlossen ist. Ist da
8-Bit-Peripherie benutzt man einen char * (besser uint8_t *). Ist da
16-Bit-Peripherie benutzt man einen uint16_t *.

Um den cast kommst du nicht herum wenn du ordentlichen Code produzieren
willst den ein Compiler auch ohne Warning schluckt. 0x5513 ist eben kein
Addresse sondern eine Zahl. Um aus einer Zahl eine Addresse zu machen
mußt du diese Zahl umwandeln (casten).

BTW:
Nicht jede Architektur läßt 16-Bit Speicherzugriffe auf ungerade
Addressen zu. Und selbst wenn sie es tut sind die meist schreklich
ineffektiv da aus dem einen Zugriff häufig zwei werden.

Matthias

Autor: müllo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube, jetzt habe ich es geschluckt :))) Es geht also darum, dass
mittels cast (typ *) aus der jeweiligen Typvariablen eine
Zeigervariable (Adressvariable) wandelt. Vielen Dank an Euch Beide...


Kannst Du mir nochmal die Sache mit den Zugriffen auf ungerade Adressen
und daraus resultierende Probleme näher erläutern? Wie kann ich denn als
Programmierer dieses umgehen, zumal ich ja bei 8-Bit Zugriffen ebenfalls
auf ungerade Adressen zugreifen könnte?

Schonmal vielen Dank und schönes Wochenende...

müllo

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Das ganze hängt erstmal stark von der Architektur ab. Bei x86 kannst du
z.B. beliebige Zugriffe auf jede Addresse machen.

Ein 8-Bit Zugriff auf ungerade Addressen ist kein Problem. Aber ein
16-Bit Zugriff auf eine ungerade Addresse ist eben nicht auf jeder
Hardware möglich. SH4 erlaubt z.B. nur 16-Bit Zugriffe auf gerade
Addressen. Dito für 32Bit-Zugriffe. Da muß die Addresse eben x%4==0
erfüllen sonst wirft der Prozessor eine Exception. ARM macht das AFAIK
ganz ähnlich nur das dort jeder Zugriff die Bedingung x%4==0 erfüllen
muß.

x86 führt diese "unaligned"-Speicherzugriffe zwar aus macht aber
effektiv zwei "aligned"-Zugriffe (die allerdings atomar, d.h. nicht
unterbrechbar, sind) und bastelt das Ergebnis dann wieder zusammen.


Matthias

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht vergessen: memory-mapped IO (um sowas geht's ja hier) ist ein
typischer Kandidat für einen `volatile' qualifier.  Also

volatile char *z_reg = (volatile char *)0x5513;

Damit wird der Compiler gezwungen, tatsächlich jedesmal beim
Auftauchen von "*z_reg" auch auf den Speicherbus (und damit den
EA-Baustein) zuzugreifen, ohne den Wert zwischendrin zu cachen.  (Die
AVR-IO-Register machen letztlich auch genau dies im AVR-GCC.)

Autor: müllo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Herzlichen Dank an Euch beide...wenn ich beim Durchlesen der restlichen
Kapitel noch "blöde" Fragen habe, nerve ich nochmal.

Schönes Wochenende und viele Grüße
müllo

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.