Pointer (sPtr, dPtr, ePtr)
Pointer are special intrinsic variables. Intrinsic means, that the content of the variable is interpreted as a memory address. String variables and memory blocks are also intrinsic variables. Pointer have a special relevance: Just as with Word variables; you can do calculations with them. In addition they are memory block objects, for example p.ByteValue(0) = 0x77 etc. The controller has three different memory segments, therefore three different pointer types haqve been implemented Data Type. These are:
- sptr: Pointer to a RAM address (sram segment)
- dptr: Pointer to a Flash address (data segment)
- eptr: Pointer to a eeprom address (eeprom segment)[/list]
You may also use a pointer to access any address such as within a memory block or a Flash-Table : Example in the Data segment (Direct access):
dim pd as dptr pd = table.Addr print "pd = 0x";hex(pd);" ";34;pd.StringValue(2,12);34 do loop data table .dw myfunc1 .db "Menu Nr. 1 " .dw myfunc2 .db "Menu Nr. 2 " .dw myfunc3 .db "Menu Nr. 3 " enddata
This is similar to the access via Sram, Flash or eeprom interface, but then you must use absolute addresses instead of pointer (this is not really something new). Pointer offer another speciality: Super Imposing using Structures.
SuperImpose
SuperImposing ist das „darüberlegen“ einer Strukturdeklaration auf einen beliebigen Speicherbereich. D.h. wenn man bspw. eine Struktur in Form eines Menüelements deklariert hat, lässt sich mit Pointern diese Strukturdeklaration auf den Speicherbereich abbilden/maskieren und kann dann die elemente der Struktur elegant lesen. Das SuperImposing/Maskieren von Strukturdeklarationen auf Speicherbereiche ist auf die Verwendung mit Pointern beschränkt.
Syntax
Die Syntax ist denkbar einfach, wobei jedoch bestimmte Vorgaben einzuhalten sind. Bei einer Strukturdeklaration handelt es sich um eine virtuelle Definition, welche dem Compiler mitteilt wie der Zugriff erfolgen soll: mypointer.<StrukturName>[( Index )].<Strukturelement> Ist das Strukturelement eine weitere Struktur, verschachtelt sich der Aufruf entsprechend tiefer.
Index ist ein optionaler Konstantenwert bzw. ab Version 2013.r5 ein Ausdruck (z.B. Variable), der den Startoffset auf Basis der Gesamten Strukturgröße ergibt. D.h. ist die Struktur mitsamt seiner Elemente 4 Bytes groß, würde Index = 2 zu einer Startadresse + 8 führen, ab der die Struktur über den Speicherbereich gelegt wird.
Anwendung
Strukturdeklaration:
struct eNTRY word fnAddr string text[12] endstruct
Pointer für Flash-Segment dimensionieren:
dim pd as dptr
Pointer mit Adresse der Tabelle belegen:
pd = table.Addr
Indirekter Zugriff über Strukturdeklaration, die ab der im Pointer abgelegten Adresse über den Speicherbereich gelegt wird (superimpose). Bei Angabe eines Arrayindex bei einer Struktur, wird der Offset automatisch berechnet:
print "fnAddr = 0x";hex(pd.eNTRY(0).fnAddr);", menu text = ";34;pd.eNTRY(0).text;34 print "fnAddr = 0x";hex(pd.eNTRY(1).fnAddr);", menu text = ";34;pd.eNTRY(1).text;34 print "fnAddr = 0x";hex(pd.eNTRY(2).fnAddr);", menu text = ";34;pd.eNTRY(2).text;34
Die Tabelle im Flash:
data table .dw myfunc1 .db "Menu Nr. 1 " .dw myfunc2 .db "Menu Nr. 2 " .dw myfunc3 .db "Menu Nr. 3 " enddata
Beispielprogramm
- pointer.luna
const F_CPU=20000000 avr.device = atmega328p avr.clock = F_CPU avr.stack = 64 uart.baud = 19200 uart.recv.enable uart.send.enable struct eNTRY word fnAddr string text[12] endstruct dim a as byte dim ps as sptr dim pd as dptr dim m as MemoryBlock print 12;"pointer and superimpose example" print m.New(64) m.WordValue(0) = 0xaabb m.CString(2) = "entry Nr. 1 " m.WordValue(14) = 0xccdd m.CString(16) = "entry Nr. 2 " m.WordValue(28) = 0xeeff m.CString(30) = "entry Nr. 3 " ps = m.Ptr 'Speicheradresse der MemoryBlock-Daten pd = table.Addr 'Speicheradresse der Tabelle im Flash 'direkt über Objektfunktionen print "(sram) ";34;ps.StringValue(2,12);34 print "(flash) ";34;pd.StringValue(2,12);34 print 'SuperImpose ' 'SuperImposing ist das "darüberlegen" einer Strukturdeklaration auf einen beliebigen Speicherbereich. 'D.h. wenn man bspw. eine Struktur in Form eines Menüelements deklariert hat, lässt sich mit Pointern 'diese Strukturdeklaration auf den Speicherbereich abbilden und kann dann die elemente der 'Struktur elegant lesen. Bei Angabe eines Arrayindex (Konstante) bei einer Struktur, wird der 'Offset automatisch berechnet. print "sram:" print "fnAddr = 0x";hex(ps.eNTRY(0).fnAddr);", menu text = ";34;ps.eNTRY(0).text;34 print "fnAddr = 0x";hex(ps.eNTRY(1).fnAddr);", menu text = ";34;ps.eNTRY(1).text;34 print "fnAddr = 0x";hex(ps.eNTRY(2).fnAddr);", menu text = ";34;ps.eNTRY(2).text;34 print print "flash:" print "fnAddr = 0x";hex(pd.eNTRY(0).fnAddr);", menu text = ";34;pd.eNTRY(0).text;34 print "fnAddr = 0x";hex(pd.eNTRY(1).fnAddr);", menu text = ";34;pd.eNTRY(1).text;34 print "fnAddr = 0x";hex(pd.eNTRY(2).fnAddr);", menu text = ";34;pd.eNTRY(2).text;34 print print "Aufruf per Icall aus der Tabelle:" icall pd.eNTRY(0).fnAddr icall pd.eNTRY(1).fnAddr icall pd.eNTRY(2).fnAddr print print "ready" do loop procedure myfunc1() print "myfunc 1" endproc procedure myfunc2() print "myfunc 2" endproc procedure myfunc3() print "myfunc 3" endproc 'Wichtiger Hinweis: 'Adressen von Labels, Objekten oder Methoden liegen im Flash immer an einer Word-Grenze, sie werden 'im Flash-Objekt daher auch als Word-basierte Adresse abgelegt. Möchte man mit der Byte-Adresse arbeiten, 'muss man den Wert wie im Assembler mit 2 multiplizieren. data table eNTRY { myfunc1, "Menu Nr. 1" } eNTRY { myfunc2, "Menu Nr. 2" } eNTRY { myfunc3, "Menu Nr. 3" } enddata