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