Bibliothek erstellen - Grundlagen

Die externen Bibliotheken werden durch einen dafür extra vorhandenen, mächtigen Bibliotheks-Editor bearbeitet und/oder erstellt. Der Bibliotheks-Editor unterstützt den Autor einer Bibliothek grafisch durch Übersichten und leicht verständlichen Auswahlmöglichkeiten beim Erstellen von Methoden und Eigenschaften.

Die eigentlichen Bibliotheksfunktionen werden klassisch in Assembler programmiert.

In den Quelltexten der Interfaces und Module können Funktionen und Makros der Standardbibliothek verwendet werden. Mit .import <label> kann ein externes Label importiert werden. Auch ist die Verwendung von Funktionen anderer Bibliotheken möglich. Durch die Verwendung der Präprozessorfunktion Defined() kann abgefragt werden, ob der Luna-Programmierer auch die notwendige Bibliothek eingebunden hat.

UM NAMENKOLLISIONEN ZU VERMEIDEN, MÜSSEN SÄMTLICHE BEZEICHNER VON DEFINES, KONSTANTEN, LABELS UND MAKROS INNERHALB EINER BIBLIOTHEK EINMALIG UND EINDEUTIG SEIN.

Es können sämtliche allgemeinen Präprozessorfunktionen des Luna-Assemblers genutzt werden wie in Inline-Assembler möglich, wie z.B. hi8(), lo8(), Schiebebefehle usw. Zusätzlich stehen spezielle Präprozessor-Befehle bereit, die nur bei der Erstellung von Bibliotheken Sinn machen (siehe unten).

Siehe auch:

Aufrufe/Sprünge von/zu Bibliotheksinternen oder externen Methoden/Subroutinen sollte immer mit dem Befehl call bzw. jmp erfolgen, außer das Ziel befindet sich innerhalb der eigenen Methode/Subroutine. Der Optimierer des Assemblers optimiert hier automatisch zu den effizienteren indirekten Varianten rcall und rjmp. Auf Controllern die diese direkten Sprünge nicht unterstützen, werden call und jmp automatisch durch rcall und rjmp ersetzt.

.regisr

Diese besondere Direktive erlaubt das Registrieren eines Labels auf einen anzugebenden Interrupt-Vektor.

Syntax
  • .regisr vectorAddr, label
;register the interrupt service routine to the timer-overflow-interrupt
;an error occours by the assembler, when the isr is already defined
.regisr  OVF0addr,__myIsr

MakeIdentifier( string )

Erstellt aus der übergebenen Zeichenkette einen Bezeichner (Symbol). Die Zeichenkette wird anschließend vom Assembler nicht mehr als Zeichenkette betrachtet, sondern als Konstantenname (Symbol). Wurde dieser Konstantenname bereits mit einem Wert belegt, kann er anschließend auch als Solcher im Assembler-Quelltext verwendet werden.

Beispiel

Zuweisung 0xf0 auf das bereits vorhande Register-Symbol PORTB. Die Konstante myport verweist dann auf die Konstante (Symbol) PORTB, sodass im Ergebnis hier der Wert von PORTB verwendet wird.

.set myport = MakeIdentifier("PORTB")
ldi  _HA0,0xf0
sts  myport,_HA0

Mit folgendem Code lässt sich beispielsweise in einem Interface ein bestimmter, im Luna-Code zugewiesener Port-Pin im Assemblerquelltext verwenden.

Luna-Code
Spi.PinMiso = PortB.2
Interface Inline-Methode "PinMiso"
.set SpiPinMisoPORT  	= MakeIdentifier(NthField({keyword},".",1))
.set SpiPinMisoPortPin	= val(NthField({keyword},".",2))
.set SpiPinMisoDDR		= MakeIdentifier("DDR"+right(NthField({keyword},".",1),1))
.set SpiPinMisoPIN		= MakeIdentifier("PIN"+right(NthField({keyword},".",1),1))
Im Library-Editor

Bei solchen Zuweisungen ist das ein wenig wie Textverarbeitung. Es wird die Eingabe des Programmierers so aufbereitet, dass man auf der Assemblerebene mit den Informationen sinnvoll arbeiten kann. Die Deklaration dieser Inline-Methode wiederum stellt sicher, dass der Programmierer ohne eine Fehlermeldung zu erhalten nur das eingeben kann, was er eingeben können soll. Dies wird hier durch den regulären Ausdruck sichergestellt.

In diesem Beispiel enthalten die vier Konstanten anschließend folgende Werte:

  • SpiPinMisoPORT = PORTB
  • SpiPinMisoPortPin = 2
  • SpiPinMisoDDR = DDRB
  • SpiPinMisoPIN = PINB