AvrTerse V1.03 (Bugfixed)
(Freeware)
(c) 2001 Kai Gossner, www.elektronikseiten.de

Ein Stark erweiterter Makro Assembler mit hochsprachenähnlichen Konstrukten für Avr 8 Bit Risc Prozessoren.
Basiert auf Jim Neil's Terse (tm)

Neuigkeiten zu AvrTerse erfahrt Ihr auf: www.elektronikseiten.de/avrterse 

  Click here for an english version of the page
  Index
 

 

^ Was ist AvrTerse?
  AvrTerse ist eine prozessorabhängige Programmiersprache für die komplette Atmel 8 Bit Avr Risc Prozessor Reihe (z.B. AT90S1200, ATmega103, ...). Man behält, wie in jeder anderen Assemblersprache, die komplette Kontrolle über den Prozessor, ohne jedoch die Übersichtlichkeit so leicht zu verlieren. Dies wird durch eine Hochsprachenähnliche Syntax ermöglicht, die jedoch nicht unbedingt angewendet werden muß. 

Da AvrTerse kompatibel zum Standard AvrAsm Assembler von Atmel ist, bleibt jedem die Option auch weiterhin offen, normalen AvrAsm Code zu schreiben. 

 

^ Wozu brauche ich AvrTerse?
  Gerade bei großen Assemblerprojekten, die bei den "größeren" Avr-Prozessoren von Atmel schon mal schnell entstehen können, verliert man ziemlich leicht die Übersichtlichkeit. Abhilfe kann z.B. ein Hochsprachencompiler (C, Pascal, Basic) schaffen. Braucht man aber effiziente Routinen (sowohl Code- als auch Zeiteffizient), ist man auf Assembler angewiesen.

AvrTerse ist der ideale Kompromiss zwischen Assemblernaher Programmierung und Übersichtlichkeit. Eine "etwas" höhere Sprache als Assembler, die jedoch nicht wie Hochsprachen zu sehr von dieser Ebene abstrahiert. Man denkt immer noch auf Registerlevel.

 

^ Lizenz
  AvrTerse ist Freeware, das heißt es darf kostenlos eingesetzt und weitergegeben werden, jedoch nur komplett und unverändert!

Solltet Ihr mit AvrTerse ein Projekt realisiert haben, erstellt bitte einen Link in den evtl. vorhandenen Internetseiten auf diese AvrTerse Seite!

Generell würde ich mich über eine Mail freuen, wie Ihr AvrTerse findet, wofür Ihr es einsetzt, oder ob Ihr Fehler gefunden habt. Nur so kann eine Weiterentwicklung meinerseits realisiert werden, denn wofür sollte ich etwas weiterentwickeln von dem ich den Eindruck habe, daß es niemand benutzt?! 

 

^ Download
  Die aktuelle Version von AvrTerse könnt ihr hier: AvrTerse.zip downloaden.

Das Archiv beinhaltet folgende Dateien:

AvrTerse.exe   Der Assembler
Index.html     Diese Datei

 

^ Installation von AvrTerse
  AvrTerse läßt sich direkt in AvrStudio einsetzen. Da es ein AvrStudio kompatibles Object file erzeugt, empfiehlt es sich auch stark es direkt in AvrStudio einzubinden. So ist ein einfaches simulieren von Code schnell und einfach möglich.

AvrTerse.exe kopiert man in das Programmverzeichnis von AvrStudio. Danach gibt es 2 Installationsmethoden:

Die permanente: Möchte man es dauerhaft austauschen, löscht man avrasm32.exe aus dem Programmverzeichnis und benennt AvrTerse.exe in avrasm32.exe um.

Die projektbezogene: Man öffnet ein bestehendes Projekt, oder erstellt ein neues. Unter dem Menüpunkt "Project -> Projectsettings" von AvrStudio läßt sich der Assembler auswählen. Einfach AvrTerse.exe auswählen und schon ist es einsetzbar.

 

^ Erweiterungen zu Atmels AvrAsm
  Generell kann man davon ausgehen, daß AvrAsm Code von AvrTerse assembliert werden kann. Bei der Entwicklung von AvrTerse war das ein mir sehr wichtiger Punkt, da es viel fertigen Code für die Avr Prozessoren gibt (z.B. Application notes).
Bisher sind mir keine nicht compilierbaren Sourcecodes in die Hände gekommen, ich möchte jedoch nicht generell ausschließen, daß es solche gibt.
  • AvrTerse kann mehrere Befehle in einer Zeile verarbeiten:
    Dazu müssen lediglich die Befehle mit dem Zeichen # voneinander getrennt werden.
     
    Beispiel: Entspricht:
    ldi r16, 5 # sbi r16, 5 ldi r16, 5
    sbi r16, 5
      
  • Der Bezeichner $ beinhaltet den Program Counter VOR Ausführung eines Befehles.
     
  • AvrTerse hat einige Direktiven, die AvrAsm nicht kennt, ohne auf AvrAsm Direktiven zu verzichten.
    Siehe dazu unter dem Punkt Direktiven
      
  • AvrTerse bietet einige Hochsprachenähnliche Konstrukte, die den Code übersichtlicher machen.
    Siehe dazu unter dem Punkt Konstrukte
     
  • AvrTerse Sourcecode kann man durch die oben genannten Punkte ziemlich frei formatieren.
    Einrückungen und Zeilenumbrüche sind an (fast) jeder beliebigen Stelle möglich, ein Zusammenhang zwischen Befehlen läßt sich durch Nebeneinanderschreiben  besser verdeutlichen.

 

  Direktiven
^   Die .count Direktive
  .count <n>
     <befehle>
.endcount

<befehle> wird <n> mal hintereinander compiliert.

Beispiel: wird compiliert als:
.count 3
     nop
.endcount
nop
nop
nop

 

^   Die .echo Direktive <neu ab Version 1.01>
  .echo <Parameter> [, <Parameter> [, ...]]

Die Parameter werden vom Assembler während der Assemblierung ausgegeben. So lassen sich Debug Meldungen einfach anzeigen. Ausgegeben werden können Strings, Konstanten, Ausdrücke, Def- und Equ-Bezeichner und Register.

Beispiel: Ausgabe des Assemblers:
.echo "8515-Unterstützung in der Beta Phase"
.equ devtype = 8515
.echo "Wert von equ devtype:", devtype
 -> 8515-Unterstützung in der Beta Phase

 -> Wert von equ DevType: 8515

 

^   Die .if / .else / .endif Direktive
  .if <n>
     <befehle1>
.endif

.if <n>
     <befehle1>
.else
     <befehle2>
.endif

Ist die Konstante <n> True (!= 0), werden nur der Bereich <Befehle1> compiliert. Ist <n> False (== 0), wird der Bereich <Befehle2> compiliert. Ist keine else-Direktive vorhanden, so wird überhaupt kein code erzeugt!

Beispiel: wird compiliert als:
.equ par = 1
.if par
     ldi r16, 10
.else
     nop
.endif
ldi r16, 10

 

^   Die .macro / .endmacro Direktive
  .macro <name>
     <befehle>
.endmacro

Ein Makro darf in AvrTerse, im Gegensatz zu dem Standard AvrAsm auch andere Makros aufrufen, also rekursiv arbeiten.

Beispiel: wird compiliert als:
.macro test1
     subi r16, @0
.endmacro
.macro test2
     ori r16, @0
     test1 @0
.endmacro
test2 8
ori r16, 8
subi r16, 8

 

^   Die .memmap Direktive <neu ab Version 1.01>
  .memmap

Zeigt nach der Assemblierung eine kurze Tabelle mit Informationen zu belegten und unbelegten Speicherbereichen des Zielprozessors an. Außerdem wird angezeigt, wie viele words Flash-Speicher frei sind.

Beispiel: Interpretation:
0000-0009: 1
000A-0014: 2
0015-001D: 1
001E-01FE: 0
Free code-mem: 482 words
Speicherbereich wurde 1* beschrieben
Speicherbereich wurde 2* beschrieben
Speicherbereich wurde 1* beschrieben
Speicherbereich ist leer
482 words an Programmspeicher sind ungenutzt

Ein mehrfaches Beschreiben kommt durch falsche
.org Direktiven zustande und sollte vermieden
werden!

 

  Konstrukte
    Algrebraische Konstrukte
^     Rechts-assoziative unäre Operationen
  <register> <operator> [C]

Führt die durch <Operator> bestimmte unäre Berechnung durch. Steht ein C hinter <Operator> so wird eine zu <Operator> äquivaltente Berechnung, die das Carry Bit berücksichtigt durchgeführt:

Beispiele: wird compiliert als:
r16 --
r16 ++
r16 <<
r16 <<C
r16 >>
r16 >>C
dec r16
inc r16
shl r16
rol r16
shr r16
ror r16

 

^     Links-assoziative unäre Operationen
 

<operator> <register>

Beispiele: wird compiliert als:
-r16
~r16
com r16
not r16

 

^     Binäre Operationen
  <register> <operator> [C] <Register/Konstante>

Führt die durch <Operator> bestimmte binäre Berechnung durch. Steht ein C hinter <Operator> so wird eine zu <Operator> äquivaltente Berechnung, die das Carry Bit berücksichtigt durchgeführt.

Mögliche Operatoren:  Bedeutung:
=
+
-
&
|
^
?
Zuweisung
Addition
Subtraktion
Bitweises Und
Bitweises Oder
Bitweises Exklusiv oder
Vergleich

Beispiel: wird compiliert als:
r16 + r1
r16 +C r1
r16 + 14
r16 & r12
r16 ? 15
r16 ? r12
r16 ?C r12
add r16, r1
adc r16, r1
adi r16, 14
and r16, r12
cpi r16, 15
cp  r16, r12
cpc r16, r12

 

^     Port-Zuweisung von Registerinhalten
  IOP(<portnummer>) = <register>

Dem Port <portnummer> wird der Inhalt von <register> zugewiesen.

Beispiel: wird compiliert als:
IOP(portd) = r16 out portd, r16

 

^     Register-Zuweisung von Portinhalten
  <register> = IOP(<portnummer>)

Der Inhalt von <portnummer> wird dem Inhalt von Port <register> zugewiesen.

Beispiel: wird compiliert als:
r16 = IOP(pinf) in r16, pinf

 

^     Bitänderungen von Registern
  <register>.<bitnummer> = <n>

Setzt Bit <bitnummer> von <register> auf den Wert <n>

Beispiel: wird compiliert als:
r16.3 = 1
r16.2 = 0
ori r16, (1<<3)
andi r16, not(1<<2)

 

    Kontrollstrukturen
^     Bitabhängige Codeausführung
  <register>.<bitnummer> == <n> {
     <befehl>
}

IOP(<portnummer>).<bitnummer> == <n> {
     <befehl>
}

Entspricht der Zustand von Bit <bitnummer> von <register>, bzw. <portnummer> dem Wert <n>, wird der Befehl ausgeführt. Sonst wird er übersprungen. 
Es darf nur ein Befehl enthalten sein!

Beispiele: wird compiliert als:
IOP(pinb).5 == 0 {
     ldi r16, 2
}

r16.7 == 1 {
     ldi r16, 2
}

sbis pinb, 5
ldi  r16, 2


sbrc r16, 7
ldi  r16, 2

 

^     If Then Else Konstrukt
  <vergleichsoperator> {
     <befehle1>
}

<vergleichsoperator> {
     <befehle1>
},{
     <befehle2>
}

Ist durch einen vorgehenden Vergleich die durch den Vergleichsoperator ausgedrückte Bedingung wahr, so wird <befehle1> ausgeführt, sonst, <befehle2>

Beispiel: wird compiliert als:
r16 ? 15 == {
     nop
}
cpi  r16, 15
brne ifzw2
nop
ifzw2:

 

^     Postchecked While Konstrukt
  {
    <befehle>
} <vergleichsoperator>

Führt <befehle> mindestens einmal aus. Ist die Bedinung <vergleichsoperator> erfüllt, wird <befehle> wiederum ausgeführt.

Beispiel: wird compiliert als:
count = 15
{
     count--
} !=
ldi count, 15
loop:
dec count
brne loop

 

^ Aufrufparameter von AvrTerse
  AvrTerse ist ein Kommandozeilen Assembler, wie auch AvrAsm. Um die Kompatibilität zu bewahren, sind auch die Aufrufparameter des Assemblers sehr ähnlich:

avrterse [-m | -i | -g] [-d] [-w] <infile> <listfile> <romfile>

-m generiert Motorola S-record format
-i generiert Intel Hex format
-g generiert Generic format (ebenfalls noch nicht unterstützt)

-w relative Sprünge werden über die romgrenzen hinaus "verbogen". So kann man auf kleinen Prozessoren selbst mit einem RJMP jede stelle des Programmspeichers anspringen

-d erzeugt ein Debugfile im Verzeichnis des Assembler files. Der Assembler wird dadurch sehr langsam

<infile>   ist der Name des Assemblerfiles
<listfile> der Name des zu erstellenden Listfiles
<romfile>  der Name des .hex files

Beispiel:

avrterse -i -w test.asm test.lst test.rom

 

^ Versionsgeschichte
   
Version Änderungen  
1.03 Einige Bugfixes: Falsche Tokenisierung von Makro Parametern @0-@9, Falsche Parametergrenzen von STS, Segmentgrößenfehler beseitigt!

12.09.01: Weitere Bugfixes. Einige der Konstrukte wurden nicht korrekt compiliert. Die Fehler sind alle behoben und nach ca. 5 Projekte in denen ich AvrTerse eingesetzt und debugt habe, sollte es nun endlich als stabil gelten ;-)

1.02 Bugfix: Intel Hex Codeerzeugung konnte unter bestimmten Bedingungen falsche Checksummen erzeugen
1.01 Programmierung der .ECHO und .MEMMAP Direktive
1.00 Erste Version

 

^ Bekannte Fehler
  Bisher sind noch keine wirklichen Fehler bekannt, wenn man mal von den noch ziemlich schlecht formulierten Fehlermeldungen absieht.

AvrTerse braucht ungefähr 3 mal so lange wie AvrAsm, um ein File zu assemblieren. Das wird jedoch in einer der nächsten Versionen ändern!

 

^ Kontakt
  Habt Ihr irgendwelche Fehler in AvrTerse gefunden, vermisst irgendein Feature, habt Fragen zu AvrTerse, oder wollt Beispielcode haben, könnt Ihr mir an:

Webmaster@Elektronikseiten.de

eine Mail schicken. Generell lohnt sich sicherlich auch mal ein Besuch von www.Elektronikseiten.de

Das war jetzt genug Werbung fürs erste ;-)

 

^ Copyright-Anmerkungen
  Copyright 2001 Kai Gossner. Co-copyright Besitzer ist Jim Neil als Erfinder von Terse für x86 Plattformen.

Terse (tm) ist ein eingetragenes Markenzeichen von Jim Neil. Sein Terse hat mich zur Entwicklung von AvrTerse inspiriert. Schaut euch doch einfach mal seine Seite an: www.terse.com

Andere hier genannte Produkt und Firmennamen können ebenfalls Markenzeichen ihrer jeweiligen Inhaber sein.