Bascom(P) unter Linux       

von Ralf Beesner                  
Elektronik-Labor   Projekte   AVR 





Überblick

Ich nutze Linux seit 1998, hatte mich inzwischen weitgehend von Windows gelöst und nur noch auf meinem Dienst-Notebook ein "Not-Windows". Als ich 2007 begann, mich für die Mikrocontrollerprogrammierung unter Bascom zu interessieren, war das ein lästiger Rückschritt, der häufiges "Umbooten nach Windows" erforderte.

Man kann zwar prinzipiell Windows-Programme mit "Wine" unter Linux ausführen, aber viele laufen halt doch nicht anständig und erfordern Abstriche bei der Funktionalität.

"Wine" stellt ein rekursives Akronym dar, und der vollständige Name "Wine Is Not an Emulator" erklärt, warum manche kleinere Programme gut funktionieren, einige viel nachgefragte mittelprächtig (z.B. ältere Microsoft-Office-Versionen) und manche "Exoten" eher schlecht bis gar nicht:

Wine ist kein Emulator wie Vmware, VirtualBox, QEmu oder DosBox, die versuchen, eine PC-Hardware mehr oder weniger vollständig zu emulieren und einem Betriebssystem wie Windows einen PC vorzugaukeln, sondern Wine ist lediglich eine Zwischenschicht, die einem einzelnen Windows-Programm vorgaukelt, auf einem Windows-Betriebssystem zu laufen. Wine fängt also Betriebssystemaufrufe des Windows-Programmes ab und setzt sie in Linux-Betriebssystemaufrufe um und umgekehrt.

Dies hat Vor- und Nachteile:

Der Vorteil ist, dass die Windows-Programme nicht allzusehr ausgebremst werden, da ihr Binärcode vom verwendeten Intel- oder AMD-Prozessor direkt "verstanden" wird; ein Emulator müsste Maschinenbefehl für Maschinenbefehl komplett übersetzen, Wine kann das meiste direkt an den Hardware-Prozessor "durchreichen".

Der Nachteil ist, dass die Windows-Umgebung ein "moving target" ist, ständig kommen neue DLLs und harwarenahe Betriebssystemaufrufe hinzu, die verzögert oder gar nicht in "Wine" aufgenommen und ggf. nicht verstanden werden. Ein Emulator hat es da einfacher; er stellt eine (im allgemeinen veraltete) virtuelle Hardware zur Verfügung, und das Gast-Betriebssystem sowie die Gast-Anwendungen haben damit zurechtzukommen.

Ein weiterer Nachteil ist, dass Wine an die Intel-Architektur gebunden ist; Wine läuft also leider nicht auf ARM-Boards wie z.B. dem RaspBerry Pi.

Bascom ist aus Wine-Sicht offenbar ein Exot. Die Demo-Version lässt sich problemlos installieren (mit der Vollversion gibt es möglicherweise Probleme mit dem Online-Updater, das habe ich aber nicht ausprobiert), aber wenn man es aus einem xterm startet, erscheinen haufenweise Fehlermeldungen auf der Konsole, weil Wine allerlei Betriebssystemaufrufe nicht nach Linux übersetzen kann.

Je nach Wine-Version kann es passieren, dass Bascom komplett "abschmiert", wie es so schön drastisch heißt, oder nach einer Weile zwar doch noch startet, aber dann auch im Leerlauf einen Prozessorkern zu 100% auslastet und sich im Antwortverhalten recht "zäh" anfühlt.

Früher war Wine auch berüchtigt für Regressionen: nach einem Update der Wine-Version kam es manchmal vor, dass etwas nicht mehr funktionierte, das vorher keine Probleme machte.

Es gibt aber einen Ausweg aus dem Dilemma: neben dem grafikbasierten bascavr.exe gibt es das unscheinbare Kommandozeilenprogramm bascomp.exe, das die Kernaufgabe, nämlich die Übersetzung eines *.bas-Files in ein *.bin- oder *.hex-File, genauso gut erledigt.

Bascomp.exe läuft problemlos unter Wine, da es wohl nur sehr grundlegende Windows-Systemaufrufe tätigt. Ohne die grafische Programmierumgebung (IDE) wird jedoch das Schreiben eines Bascom-Programmes und das Flashen sehr unkomfortabel. Unter Linux gibt es zwar allerlei Editoren und IDEs, aber sie kennen den Bascom-Dialekt nicht und können daher kein brauchbares "syntax highlighting", also das "Einfärben" der Bascom-Befehle, das den Quellcode erst übersichtlich macht.

Ich hatte daher zunächst versucht, mir ein paar Hilfsmittel zu basteln. Unter Linux gibt es einige Editoren, denen man eigene Syntax-Files "unterschieben" kann, ohne das Editor-Programm neu kompilieren zu müssen. Außerdem entstand ein kleines Skript, das das Kompilieren und Flashen vereinfacht (also den Aufruf von wine/bascomp.exe und von avrdude automatisiert).

Mittlerweile nutze ich die recht kompakte Linux-IDE "Geany", die - einmal eingerichtet - nicht mehr viel gegenüber dem Original vermissen lässt.


Bascom(p) installieren

Zunächst ist natürlich Wine mit dem distributionseigenen Paketmanager zu installieren. Dann lädt man die Bascom-Demo herunter und installiert sie unter Wine mit "wine setup.exe". Das gesamte virtuelle Wine-Filesystem liegt ja im versteckten Ordner .wine des angemeldeten Users, also z.B. "/home/ralf/.wine". Die Bascom-spezifischen Files liegen dann unter "/home/ralf/.wine/drive_c/Program Files/BASCOM-AVR".

Ggf. muss man im Dateimanager seines Vertrauens erst einmal die Anzeige versteckter Ordner und Files aktivieren.

Will man nur die Kommandozeilenversion bascomp.exe nutzen, kopiert man der Einfachheit halber die relevanten Files in einen neuen Ordner "bascomp" im Heimatverzeichnis, z.B. nach "/home/ralf/bascomp":

- den Ordner LIB
- bascomp.exe
- BASC-AVR.DLL
- BASCAVR.chm (Help-File)
- bscavrl.dll (Lizenzdatei)
- alle *.DAT und *.dat - Files


Man kann auch "exotische" Dat-Files weglassen und lediglich die *.dat-Files für tatsächlich genutzte Mikrocontroller kopieren.

Danach kann man Bascom-AVR deinstallieren (im xterm "wine uninstaller" aufrufen).

Ist auf dem Rechner Windows vorhanden und dort Bascom bereits installiert, kann man sich die Installation der Bascom-Demo unter Wine selbstverständlich ersparen und die oben genannten Files dort "ausborgen".

Gibt man nun in einem Terminal wine ~/bascomp/bascomp.exe ein, sollte sich bascomp mit einem umfangreichen Verwendungshinweis melden:

bascomp command line compiler version 2.0.7.x
supports all existing and future DAT files
DAT Directory :Z:\home\ralf\bascomp\*.DAT
DAT files found :80
Usage : bascomp file.bas SS=softstack FR=framesize HW=hardwarestack CHIP=index
31=ATtiny2313A
91=ATtiny48
100=ATMEGA325
.........
39=ATMega128RFA1
42=ATMega165
19=atmega64
Set baudrate, XTAL, LCD etc. with $ directives and CONFIG in your code

Ihm entnimmt man, dass bascomp ziemlich "doof" ist: die Werte für SoftStack, Framesize, Hardwarestack und MCU müssen beim Aufruf auf der Kommandozeile übergeben werden. Man kann das durchaus mit klassischen Linux-Kommandozeilenwerkzeugen wie grep, sed und awk automatisieren (ich hatte sogar damit begonnen), aber inzwischen gibt es ein bascomp-Update, das die Werte direkt aus dem *.bas-File lesen kann, wenn man bascomp mit dem Parameter "auto" aufruft.

Man lädt das Update hier herunter und überschreibt die alte Version "/home/ralf/bascomp/bascomp.exe" mit der neuen Version (die neue ist 113 kB groß, die alte nur 102 kB).


Geany installieren und konfigurieren

"Geany" ist eine kompakte IDE, die weitgehend "ausentwickelt" ist und sich nur noch wenig ändert. Sie kann auf den gängigen Linux-Varianten über die Paketverwaltung installiert werden. Anscheinend kann man ihr aber keine komplett neuen Syntax-Files "unterschieben". Ich habe daher die Sprache "Freebasic" geopfert und das File "filetypes.freebasic" modifiziert. Neben den zusätzlichen Schlüsselwörtern für Bascom-spezifische Befehle sind auch Schlüsselwörter für einige AVR-Register dazugekommen.

Außerdem kann man in diesem File auch ein individuelles Farbschema hinterlegen. Die Farben sind dem BASCOM-Styling nachempfunden. Schlüsselwörter werden zwar nicht in Blockbuchstaben umgewandelt, aber trotzdem sieht die Darstellung halbwegs gewohnt aus.

Geany bietet die Möglichkeit, mit dem Pulldown-Menüpunkt "Neu (aus Vorlage) - file.bas" ein "Leer-Gerüst" zu laden, das im File "file.bas" vordefiniert wurde.

Über die Geany-Menüpunkte (bzw. die Werkzeugleisten-Icons) "Kompilieren" und "Erstellen" werden die Skripte (Batch-Files) "c-bas" und "c-f-bas" aufgerufen, die ihre Ausgabe in einem xterm-Fenster präsentieren. "Erstellen" kompiliert und flasht das entstandene hex-File "in einem Rutsch".


Skript "c-bas"

Unter Linux werden Zeilenenden nur mit Linefeed (0x0A) abgeschlossen, unter Windows mit Linefeed + Carriage Return (0x0D). Bascomp.exe steigt mit einer Fehlermeldung aus, wenn Carriage Returns fehlen. Der Stream-Editor "sed" ergänzt aufgrund einer kryptischen Befehlsfolge jedes Linefeed mit einem Carriage Return und schreibt das Ergebnis in eine Datei programmname.dos. Diese wird dann an wine/bascomp übergeben. Da wine und bascomp ziemlich "geschwätzig" sind, schickt das Skript alle Programm- und Fehlermeldungen ins Nirwana (nach /dev/null).

Zum Abschluss wird geprüft, ob bascomp.exe einen Fehler entdeckt und eine Datei programmname.err angelegt hat. Diese wird ggf. im xterm ausgegeben. Ansonsten wird "compilation ok" gemeldet und das Fenster selbsttätig geschlossen.


 

Skript "c-f-bas"

Im oberen Teil muss man zuerst den verwendeten Programmer eintragen, im meinem Fall ist es ein USBASP. Auskommentiert sind zwei Beispiele für einen selbstdefinierten seriellen Programmer (Franzis-Lernpaket-Mikrocontroller) und meinen alten SP12-Programmer für die parallele PC-Schnittstelle. Sie können als Beispiel dienen, da der als aktiv eingetragene USBASP keine besonderen Parameter wie Schnittstellen-Name oder Baudrate benötigt.

Danach folgt der Programmcode von "c-bas", und dann wird es kryptisch. Der verwendete Microcontroller soll aus dem *.bas-File ausgelesen und an avrdude übergeben werden. In einem Bascom-Programm können Zeilen wie

  $regfile = "m8def.dat"       ' used microcontroller
' $Regfile="Attiny45.dat"
'$regfile = "attiny13.dat"

stehen - führende Leerzeichen, Groß-Kleinschreibung, angehängte Kommentare und auskommentierte Zeilen, die erkannt und verworfen werden müssen. Aus der (gültigen) ersten Zeile darf nur ein schlichtes m8 übrigbleiben. Verwendet werden nur die Standard-Linux-Bordmittel grep, sed, cut und tr. Die Kommentare im Skript "c-f-bas" erklären die einzelnen Schritte.


 

Alles an seinen Platz

Die beiden Skripte müssen in einen Ordner kopiert werden, der im Suchpfad liegt. Hat man einen ~/bin-Ordner im Home-Verzeichnis, können sie da rein, ansonsten kopiert man sie nach /usr/local/bin.

Die modifizierten Files "filetypes.freebasic" und "file.bas" gehören in die versteckten Ordner /home/ralf/.config/geany/filedefs bzw. /home/ralf/.config/geany/templates. Optional kann die Datei ui_toolbar.xml nach /home/ralf/.config/geany kopiert werden, sie blendet ein paar Icons aus der Werkzeugleiste aus. Nach dem Kopieren sollte man ggf. Eigentümer und Gruppe der Files anpassen und die Skripte ausführbar machen.

Schließlich muss man noch nach dem Start von Geany unter "Erstellen - Kommandos zum Erstellen konfigurieren" das Öffnen von xterms und die Aufrufe der Batch-Files eintragen.

 

Sollte avrdude nicht mit Userrechten (jedoch mit Rootrechten) funktionieren, fehlt eine passende udev-Regel für den verwendeten Programmer unter /etc/udev/rules.d . Wie man sie anlegt, lässt sich schnell "ergoogeln".


Download der Files  0216-bascomp-unter-linux.tar.gz


#! /bin/bash

# Usage: c-f-bas "filename without .bas"

#-------------------------------------

# insert your Programmer here:

# a self defined programmer:
#PROG='burkhard'
#PORT='/dev/ttyS0'
#DLAY='20' # important; slow down the Programmer if the MCU's clock is below 8 MHz

# parallel port programmer "SP12"
#PROG='sp12'
#PORT='/dev/parport0'
# DLAY='10' # important; slow down the Programmer if the MCU's clock is below 8 MHz

# usbasp
PROG='usbasp'
PORT='usb'
DLAY='10'

#-------------------------------------

# We check if a nonexisting filename or no filename was called
# the extension "bas" is added automatically
# the script ends if the filename does not exist

if [ -a ./$1.bas ]; then
echo " compiling ...."
else
echo " empty file or wrong filename "
sleep 2
exit
fi

# if the source code was edited with a linux editor, lines may not end
# with carriage returns. We add them with sed and write into a file
# named "filename.dos":

cat $1.bas | sed 's/$'"/`echo \\\r`/" > $1.dos 2> /dev/null

# We call bascomp and hand over the filename:
# all bascom outputs are sent to /dev/null

wine ~/bascomp/bascomp.exe $1.dos auto 2> /dev/null 1> /dev/null

# now we print "ok" if the source was compiled
# or print the content of the error file and exit (if compilation failed):

if [ -a ./$1.err ]; then
cat ./$1.err
sleep 3
exit
else
echo " compilation ok "
# sleep 1
fi

#-------------------------------------

# here the avrdude part starts:

# we try to cut out the name of the micocontroller from the *.bas file
# first "sed" command deletes all blanks from the lines
# first "grep" deletes all $regfile statements that have been commented out (like '$regfile )
# second "grep" extracts the line containing $regfile
# first "cut" cuts out the second expression after the delimiter "="
# second "cut" cuts off comments at the and of the valid $regfile line
# "tr" transforms upper case letters to lowercase letters
# second "sed" deletes the carriage return
# now we have an expression like "m8def.dat"

REG=$( sed 's/ //g' $1.bas | grep -v "^'$regfile" | grep '$regfile' | cut -d "=" -f 2 | cut -d "'" -f 1 | tr A-Z a-z | sed 's/\r//' )

# the "PART" name that avrdude expects is somewhat different from the regfile's micocontroller name
# so first sed deletes "def" (like in m8def.dat)
# second sed deletes ".dat"
# now we have an expression like "m8"
# last cut removes "" - it cuts out m8 - this is the form avrdude expects

PART="none"
PART=$( echo $REG | sed 's/def//g' | sed 's/.dat//g' | cut -d '"' -f2 )

# now we check if "PART" is empty or "none"

if [ -z $PART ]; then
echo "Sorry - no valid microcontroller name was handed over to avrdude!"
sleep 5
exit
fi

if [ $PART = "none" ]; then
echo "Sorry - no valid microcontroller name was handed over to avrdude!"
sleep 5
exit
fi

if [ -z $DLAY ]; then
avrdude -p $PART -c $PROG -P $PORT -U flash:w:$1.hex:i
else
avrdude -p $PART -c $PROG -P $PORT -B $DLAY -U flash:w:$1.hex:i
fi

sleep 3 # we leave the avrdude output on the screen for 3 seconds



Elektronik-Labor   Projekte   AVR