Forum: Mikrocontroller und Digitale Elektronik 8bit Pointer bei großen AVR's


von Ralf (Gast)


Lesenswert?

Hallo,

ich finde immer wieder Quellcode für ATmegas, wo zum Beispiel die 
Adresse eines Arrays in einem char (8bit) übergeben wird. Ist das auch 
noch für einen Atmega1280 zulässig?

Wenn ich es richtig verstanden habe, dann ist das SRAM der AVR's 16bit 
breit, so dass man mit einem char maximal 16*256, also 4k Speicher, 
adressieren kann. Der Mega1280 hat aber nun 8k Speicher, die sich mit 
einem char nicht mehr voll adressieren lassen.

von (prx) A. K. (prx)


Lesenswert?

Ralf schrieb:
> ich finde immer wieder Quellcode für ATmegas, wo zum Beispiel die
> Adresse eines Arrays in einem char (8bit) übergeben wird. Ist das auch
> noch für einen Atmega1280 zulässig?

Das war noch nie zulässig. Beispiel?

> Wenn ich es richtig verstanden habe, dann ist das SRAM der AVR's 16bit
> breit,

Nein. Das Flash-ROM ist es. Dessen Adressierung ist je nach Art der 
Verwendung in 16-Bit Worten (als Code) oder in 8-Bit Bytes (als Daten).

> so dass man mit einem char maximal 16*256, also 4k Speicher,
> adressieren kann.

Nein. Ausserdem fehlt die Einheit. In Bits wäre immerhin der 
Gedankengang nachvollziehbar. Nur wird die Kapazität von RAM 
üblicherweise in Bytes angegeben.

von chris (Gast)


Lesenswert?

eigentlich sind die Pointer bei den AVR's YH:YL, XH:XL, ZH:ZL 16bit 
breit 65536 Byte adressierbar was 64Kbyte macht

von Thomas E. (thomase)


Lesenswert?

Ralf schrieb:
> Hallo,
>
> ich finde immer wieder Quellcode für ATmegas, wo zum Beispiel die
> Adresse eines Arrays in einem char (8bit) übergeben wird. Ist das auch
> noch für einen Atmega1280 zulässig?

Eine Adresse wird nicht mit einem char übergeben, sondern mit einem 
char*. Und Pointer sind 16 Bit gross.

> Wenn ich es richtig verstanden habe, dann ist das SRAM der AVR's 16bit
> breit, so dass man mit einem char maximal 16*256, also 4k Speicher,
> adressieren kann. Der Mega1280 hat aber nun 8k Speicher, die sich mit
> einem char nicht mehr voll adressieren lassen.

Nein. Das RAM ist 8 Bit breit. Das Flash hat 16 Bit.

mfg.

von Ralf (Gast)


Lesenswert?

A. K. schrieb:
> Das war noch nie zulässig. Beispiel?


Beispielsweise in diesem Thread:
Beitrag "Arrays, Pointer und Schleifen (avr-gcc)"

Konkret ging es mir aber um die Funktion itoxx() von diesem Beispiel 
hier:
http://www.mikrocontroller.net/svnbrowser/irmp/main.c?view=markup

A. K. schrieb:
> Nein. Ausserdem fehlt die Einheit. In Bits wäre immerhin der
> Gedankengang nachvollziehbar. Nur wie die Kapazität von RAM
> üblicherweise in Bytes angegeben.

...gut, mein Fehler

von Ralf (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Eine Adresse wird nicht mit einem char übergeben, sondern mit einem
> char*. Und Pointer sind 16 Bit gross.

...ach da lag mein Fehler...vielen Dank

von Loocee L. (loocee)


Lesenswert?

Ralf schrieb:
> ich finde immer wieder Quellcode für ATmegas, wo zum Beispiel die
> Adresse eines Arrays in einem char (8bit) übergeben wird. Ist das auch
> noch für einen Atmega1280 zulässig?

Der Pointer auf einen bestimmten Datentyp hat nichts mit der
Verarbeitung auf Maschinenebene zu tun.

Der Benutzer sagt ich will auf char zeigen, und der Compiler
kümmert sich darum das auf Maschinenebene richtig umzusetzen.
Dabei kommen je nach Prozessor und Speichergrösse unterschiedliche
Ergebnisse zustande.

von Fritz G. (fritzg)


Lesenswert?

Du meinst die Zeile?

    val &= 0x0F;

Das ist keine Adressübergabe sondern die Kurzschreibweise für

val=val & 0x0f;

von Ralf (Gast)


Lesenswert?

Fritz Ganter schrieb:
> u meinst die Zeile?
>
>     val &= 0x0F;
>
> Das ist keine Adressübergabe sondern die Kurzschreibweise für
>
> val=val & 0x0f;

nein, nein, mir war in der Tat der Ausdruck char* xx nicht geläufig. Ich 
dachte der Pointer wäre aufgrund dem "char" nur 8bit breit.

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:
> Fritz Ganter schrieb:
>> u meinst die Zeile?
>>
>>     val &= 0x0F;
>>
>> Das ist keine Adressübergabe sondern die Kurzschreibweise für
>>
>> val=val & 0x0f;
>
> nein, nein, mir war in der Tat der Ausdruck char* xx nicht geläufig. Ich
> dachte der Pointer wäre aufgrund dem "char" nur 8bit breit.

der springende Punkt bei einem Pointer ist der Stern '*'. Die Angabe 
davor bezieht sich nur darauf, worauf der Pointer zeigt.
Denn ein Pointer auf einen char ist etwas anderes als ein Pointer auf 
einen long. D.h. der Pointer im Sinne einer Variablen die eine Adresse 
enthält nicht, die ist immer gleich groß. Aber beim Dereferenzieren, 
also beim Holen des Wertes auf das der Pointer dann tatsächlich zeigt, 
muss der Compiler ja wissen, ob sich unter der so angegebenen Adresse 
lediglich 1 Byte oder deren 4 Bytes verbergen, die umkopiert werden 
müssen.
1
  POintervariable
2
  +---------+
3
  |   o     |
4
  +---|-----+         das, worauf der Pointer zeigt. zb. ein long
5
      |               +------------+
6
      +-------------->|     5      |
7
                      +------------+
1
   long  longVar;
2
3
   long* Pointer;
4
5
   Pointer = &longVar;    // der Pointer zeigt jetzt auf die Variable
6
   *Pointer  = 5;
7
8
   long k;
9
   k = *Pointer ;          // k kriegt den Wert, auf den Pointer zeigt


wichtig ist:
nur weil du einen Pointer hast, heisst das noch lange nicht, dass du 
deswegen auch eine Speicherfläche hast, in der Werte gespeichert werden 
können.
1
Ein
2
[c]
3
  int * Ptr;
legt lediglich die Variable Ptr an. Eine Variable, die auf eine 
Speicherfläche zeigen kann, es aber im Moment noch nicht tut. Im obigen 
Schaubild entspricht das einem
1
    Ptr
2
   +------------+
3
   |            |
4
   +------------+
Also nur die Pointervariable, die noch nicht auf irgendetwas zeigt. 
Würdest du da jetzt einfach die Operation
1
  *Ptr = 8;
drauf anwenden, dann wäre das ein schwerer Fehler. Denn wie im Schaubild 
zu sehen, gibt es keinen bestimmten von Ptr ausgehenden Pfeil, der auf 
für dein Programm reservierten Speicher zeigt. Das ist aber 
Grundvoraussetzung, damit du mit einem Pointer sicher arbeiten kannst: 
Es muss einen derartigen Pfeil geben und am Ende des Pfeiles muss ein 
für das Programm reservierter Speicher sein.

von Loocee L. (loocee)


Lesenswert?

Da hätte ich noch eine Gretchenfrage, vielleicht weiss jemand
eine Antwort?

Es ist ja möglich const Variablen im Flash anzulegen, wie
würden denn diese im Falle eines AVRs mit >64K Flash per
Pointer adressierbar sein (wenn der Pointer auf Register-
Ebene nur 16 Bit gross ist)?

von (prx) A. K. (prx)


Lesenswert?

Eberhard F. schrieb:
> Es ist ja möglich const Variablen im Flash anzulegen, wie
> würden denn diese im Falle eines AVRs mit >64K Flash per
> Pointer adressierbar sein (wenn der Pointer auf Register-
> Ebene nur 16 Bit gross ist)?

Dazu musst du eine andere Art von Pointern verwenden. Beispielsweise
   char __flash *string;
Wobei dafür ein leidlich aktueller Compiler nötig ist. Früher war das 
umständlicher.

von Rolf Magnus (Gast)


Lesenswert?

Wie es tatsächlich umgesetzt ist, weiß ich zwar nicht, aber ein Zeiger 
auf Flash muss eh ein anderer Typ sein, als einer auf RAM, da ja auch 
der Zugriff anders ablaufen muß. Dann könnte man solche Zeiger auch 
größer machen als die auf RAM. Letztendlich gilt das gleiche auch für 
Zeiger auf Funktionen.

von (prx) A. K. (prx)


Lesenswert?

PS: Man kann nicht mit dem gleichen Pointer sowohl RAM wie ROM 
ansprechen.

von Martin S. (led_martin)


Lesenswert?

@Eberhard F. (loocee):

Das hängt vom Typ des verwendeten AVRs ab. Manche haben ein spezielles 
IO-Register (RAMPZ), mit dem eine Art Bankswitching möglich ist, bei 
anderen Typen gibt es das nicht, und man muß sich darum kümmern, daß die 
Konstanten / Tabellen in den unteren 64k angelegt werden. Diese 
Beschränkung gilt dann auch für indirekte Sprünge über das Z-Register, 
dort sind allerdings 128k erreichbar, da ja in Words gezählt wird.

Absolute Sprünge, und Calls können den ganzen Bereich erreichen, 
brauchen dann auch mehr Taktzyklen, Adressen auf dem Stack belegen dann 
3 Bytes statt 2. So braucht dann auch der RET einen Taktzyklus mehr.

Mit freundlichem Gruß - Martin

von chris (Gast)


Lesenswert?

Bei den AVR's ist es der Z-Pointer der RAM und Flash gemeinsam nutzen 
kann.

z.B für Flash
 ;z darf nicht mit x / y ersetzt werden da LPM sonst nicht Funktioniert 
siehe DB
 ldi    zh,High(OUT_LCD)
 ldi    zl,Low (OUT_LCD)    ;Stringadresse an den Pointer übergeben

start:
 lpm      r16,z+                   ;erst Z von lesen und dann Adresse 
Z+1
 ;Programm irgendwas
 cpi       r16,$FF                 ;Stoppbedingung
 brne    start
.
.
.

.db OUT_LCD "HELLO",$FF



Selber Pointer für RAM

RAMPZ = $0060
RAMPX = $0070
RAMPY = $0080        ;Adresse auf RAM als Namen deklarieren

 ldi    zh,High(RAMPZ) ;z kann durch x oder y ersetzt werden
 ldi    zl,Low (RAMPZ)
start:
 ld    r16,z+
 st   z+,r16
;Programm irgendwas
.
.
.
um eventuell einen größeren Bereich mit Pointer abzubacken kann man die 
Pointer "zusammenschalten"

von Loocee L. (loocee)


Lesenswert?

Ich spiele gerade ein bisschen mit const char im Flash.

Dabei zeigt sich dass der GCC (WINAVR-2010) störrisch reagiert mit
einer unklaren Fehlermeldung:

../Main_Flash_Test.c:12: warning: '__progmem__' attribute ignored

Das passiert dann wenn man einen Flash String in einer Funktion
anlegt:
1
int main (void)
2
{
3
  const char __ATTR_PROGMEM__  MyString[] = "Das ist ein String im Flash";
4
 ........
5
}
.... nicht ganz einleuchtend .... da ja eigentlich const. Das bekommt
man ja sonst auch.
Legt man dagegen den String im globalen Scope an ist es ok .....

von Karl H. (kbuchegg)


Lesenswert?

Eberhard F. schrieb:
> Ich spiele gerade ein bisschen mit const char im Flash.
>
> Dabei zeigt sich dass der GCC (WINAVR-2010) störrisch reagiert mit
> einer unklaren Fehlermeldung:
>
> ../Main_Flash_Test.c:12: warning: '__progmem__' attribute ignored
>
> Das passiert dann wenn man einen Flash String in einer Funktion
> anlegt:
>
>
1
> int main (void)
2
> {
3
>   const char __ATTR_PROGMEM__  MyString[] = "Das ist ein String im 
4
> Flash";
5
>  ........
6
> }
7
>
> .... nicht ganz einleuchtend ....

na ja. eigentlich schon einleuchtend.

> da ja eigentlich const.

das hat ja damit nichts zu tun.

Das "Problem" ist nun mal, dass derartige funktionslokale Variablen, 
wenn man es genau nimmt, erzeugt werden, wenn die Funktion betreten wird 
und zerstört werden, wenn die Funktion verlassen wird. Und das ist nun 
mal mit Variablen im Flash schwierig, egal ob const oder nicht.

von Geht's noch (Gast)


Lesenswert?

Da schreibt man eben noch
1
static
 davor, dann ist man das Lokale los.

von Loocee L. (loocee)


Lesenswert?

Karl Heinz schrieb:
> Das "Problem" ist nun mal, dass derartige funktionslokale Variablen,
> wenn man es genau nimmt, erzeugt werden, wenn die Funktion betreten wird
> und zerstört werden, wenn die Funktion verlassen wird.

Das hab ich eben anders in "Erinnerung": Ein const Variable wird
in einer Funktion nicht "at runtime" angelegt wie eine echte
Variable. Das wäre ja auch Zeitverschwendung ....

Aber ich kann mich täuschen, und jeder Compiler mag es anders machen.

von Karl H. (kbuchegg)


Lesenswert?

Eberhard F. schrieb:
> Karl Heinz schrieb:
>> Das "Problem" ist nun mal, dass derartige funktionslokale Variablen,
>> wenn man es genau nimmt, erzeugt werden, wenn die Funktion betreten wird
>> und zerstört werden, wenn die Funktion verlassen wird.
>
> Das hab ich eben anders in "Erinnerung": Ein const Variable wird
> in einer Funktion nicht "at runtime" angelegt wie eine echte
> Variable. Das wäre ja auch Zeitverschwendung ....

Ob der Compiler für eine const Variable überhaupt eine Variable anlegt 
oder nicht, musst du schon dem Compiler überlassen.
Konzeptionell kommt bei
1
void foo()
2
{
3
  const int i = 5;
4
}
die Variable i beim Betreten der Funktion zur Welt und wird beim 
Verlassen der Funktion zerstört.
Das der Compiler die Variable komplett wegoptimiert und anstelle von i 
...
1
void foo()
2
{
3
  const int i = 5;
4
  k = i;
5
}
... bei der Zuweisung gleich den bekannten Wert der Variablen benutzt, 
ändert am grundsätzlichen Konzept nichts. Denn Optimierungen werden in C 
anhand der 'as if' Regel behandelt. Der Compiler darf nach Lust und 
Laune optimieren, aber immer nur 'as if' die Optimierung nicht statt 
gefunden hätte. D.h. das Endergebnis muss dasselbe sein. Aus dieser 
'Muss' Klausel folgt unmittelbar, dass Optimierungen keine C Regeln 
ausser Kraft setzen können. Insbesonders können Optimierungen kein 
illegales Programm plötzlich legal machen.

>
> Aber ich kann mich täuschen, und jeder Compiler mag es anders machen.

Immer dieses 'jeder COmpiler macht das anders'. Nein! Es gibt Dinge, die 
sind in C so definiert. Entweder ein Compiler implementiert die genau 
so, oder er ist kein C Compiler. Scope und die damit verknüpfte Lifetime 
von Variablen fallen da zu 100% darunter.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Geht's noch schrieb:
> Da schreibt man eben noch
1
static
 davor, dann ist man das
> Lokale los.

Nö, lokal ist die Variable dann immer noch; hat aber eine andere 
Speicherklasse: static statt auto.  Damit kann die Variable dann im 
Flash oder allgemeiner einem readonly-Speicher liegen.

von Loocee L. (loocee)


Lesenswert?

Karl Heinz schrieb:

> Immer dieses 'jeder COmpiler macht das anders'. Nein!

Nö. Nicht immer. Nur jetzt gerade, und nur heute, bei diesem Thema.
Schön cool bleiben.

> Es gibt Dinge, die
> sind in C so definiert. Entweder ein Compiler implementiert die genau
> so, oder er ist kein C Compiler.

Dann kann immer noch gelten:
> Aber ich kann mich täuschen, .....

Alles klar, Herr Kommissar?

von Geht's noch (Gast)


Lesenswert?

> Damit kann die Variable dann im
Flash oder allgemeiner einem readonly-Speicher liegen.
Ja, falscher Begriff. Es ging mir nicht um die Sichtbarekeit, sondern um 
global vs lokal als Speicherort.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Eberhard F. schrieb:
> Dann kann immer noch gelten:
>> Aber ich kann mich täuschen, .....
>
> Alles klar, Herr Kommissar?

Postings wie

    "Die Sonne ist schwarz, aber ich kann mich auch täuschen"

haben genau welchen Informationsgehalt?

Genau, keinen. Der einzige Effekt ist, dass man all die anderen Leser 
verwirrt und in die Irre führt. Also lass das. Dann muss da auch keiner 
reingrätschen.

von Rolf Magnus (Gast)


Lesenswert?

Karl Heinz schrieb:
> Der Compiler darf nach Lust und Laune optimieren, aber immer nur 'as if'
> die Optimierung nicht statt gefunden hätte. D.h. das Endergebnis muss
> dasselbe sein. Aus dieser 'Muss' Klausel folgt unmittelbar, dass
> Optimierungen keine C Regeln ausser Kraft setzen können. Insbesonders
> können Optimierungen kein illegales Programm plötzlich legal machen.

Nun bewegen wir uns allerdings mit Zeigern auf Flash sowieso schon 
außerhalb der ISO-Norm, womit der Code in der Hinsicht eh illegal ist, 
egal ob mit oder ohne static. Wie also die Kombination "lokale Variable 
im Flash" gehandhabt wird, ist ganz alleine Sache des Compilers. Und 
dort wurde entschieden, daß in diesem Fall der Flash verliert und es zu 
einer normalen lokalen Variable wird, auch wenn diese const ist und sich 
am Verhalten des Programms nichts ändern würde, wenn sie im Flash 
stünde.

> Immer dieses 'jeder COmpiler macht das anders'. Nein! Es gibt Dinge, die
> sind in C so definiert.

Ja, aber _ATTR_PROGMEM_ ist dort gar nicht definiert.

von Loocee L. (loocee)


Lesenswert?

Ich bleibe mal beim Thema: 8bit Pointer bei großen AVRs

Wie macht man denn bitte einen Char Pointer "far" sodass man
auch Strings im Bereich jenseits von 64KByte Flash erreichen
kann?

Eine Anwendung wäre, viele Strings in einem ATMega256 zu
verwenden die dann die ersten 64K sprengen würden.
Zum Handlen von Strings aus dem Flash gibt es Macros wie
strcpy_P, aber die erschlagen leider nicht die Problematik >64K.

Vermutlich ist das im neueren Versionen des GCC gelöst (ich habe
es nicht gewagt mein Absturz-schwangeres Studio 6.2 diesbezüglich
zu bemühen), nicht aber im WinAVR-2010.

Nun gut, die Frage wird sich nicht auf Char Pointer bzw Strings
im Flash beschränken .......

von (prx) A. K. (prx)


Lesenswert?

Eberhard F. schrieb:
> Vermutlich ist das im neueren Versionen des GCC gelöst (ich habe
> es nicht gewagt mein Absturz-schwangeres Studio 6.2 diesbezüglich
> zu bemühen), nicht aber im WinAVR-2010.

Im WinAVR ist es gelöst, weil darin nicht der Compiler bemüht wird, 
sondern der Inhalt von <avr/pgmspace.h>. Die "pointer" der "far" 
Funktionen sind dort dementsprechend 32-Bit gross:
http://www.nongnu.org/avr-libc/user-manual/pgmspace_8h.html

> Zum Handlen von Strings aus dem Flash gibt es Macros wie
> strcpy_P, aber die erschlagen leider nicht die Problematik >64K.

Sehr wohl aber strcpy_PF.

von Loocee L. (loocee)


Lesenswert?

A. K. schrieb:
> Im WinAVR ist es gelöst, weil darin nicht der Compiler bemüht wird,
> sondern der Inhalt von <avr/pgmspace.h>.

In WinAVR_2010 (GCC 4.3.3) sind diese *_PF Makros nicht enthalten.

Da muss man wohl den GCC mit einer neueren Lib updaten .... ?
(um in den Genuss der *_PF Makros zu kommen)

Selbst wenn mir diese Makros zur Verfügung stehen sind aber die
Pointer für Strings oberhalb von 64K immer noch nicht "far".
Denn an deren Deklaration hat sich ja nichts geändert.

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.