Dieter Holzhäuser http://www.system-maker.de E-Mail: [email protected] 30.05.2011 Überarbeitung 27.02.2013 Überarbeitung 10.03.2013 Einrichten der AVR-C-Programmierung unter Ubuntu-Linux 12.04 Ein Erfahrungsbericht Vorbemerkung Der Auslöser für die vorliegende Überarbeitung war ein Problem bei den fertigen deb-Paketen, die ich bisher für die Installation von avr-gcc und avrdude benutzt habe. Bei Atmel habe ich einen um Längen besseren Ersatz gefunden, und zwar eine Toolchain mit hervorragender Dokumentation, die sich durch einfaches Entpacken installieren lies. Das Paket avrdude wird unabhängig davon aus dem Ubuntu Software-Center installiert. Ich werde zukünftig Programme nur noch mit Code::Blocks entwickeln. Daher ist der Editor gedit als Mini-Entwicklungsumgebung in diesem Artikel kein Thema mehr. Es gibt also Gründe genug für eine Überarbeitung. Worum es geht Ich schreibe C-Programme, und zwar hauptsächlich für den Mikrocontroller ATmega32 aus der AVR-Familie von Atmel. Die ganze Entwicklung findet auf dem PC statt. Weil der C-Code in den Maschinencode des Mikrocontrollers übersetzt („cross“-compiliert) wird, muss das Programm in den Speicher des Mikrocontrollers übertragen werden, denn nur dort kann es laufen. Zwecks Übertragung sind PC und Mikrocontroller durch einen Programmieradapter verbunden. Ich verwende den AVR ISP mk II von Atmel (siehe Bild oben), der bei Reichelt ( www.reichelt.de ) für etwa 40 € zu haben ist. Er ist an eine USB-Schnittstelle des PC und an das SPI (Serial Interface) des Mikrocontrollers angeschlossen. 1 Man sollte den Betrag investieren und sich nicht mit Bastellösungen herumschlagen, die meistens für die parallele oder serielle Schnittstelle gemacht sind. Solche Schnittstellen hat ein moderner PC ohnehin nicht mehr. Der Artikel handelt von meinen Erfahrungen bei der Einrichtung der integrierten Entwicklungsumgebung (IDE) Code::Blocks für die Entwicklung von C-Programmen und die Programmierung von AVR-Mikrocontrollern. Unter Letzterem ist das Schreiben von Maschinencode in den Flash-Speicher des Mikrocontrollers zu verstehen. Benötigte Programme Im Mittelpunkt stehen der C Cross Compiler avr-gcc mit seinen Bibliotheken und der Programmer avrdude. avr-gcc liefert als Endprodukt eine Datei *.hex, während avrdude mit dieser Datei den Mikrocontroller programmiert. Es ist allerdings nicht einfach, den avr-gcc und auch avrdude so aufzurufen, dass die Programme genau das tun, was sie sollen. Das liegt an den unglaublich vielen Aufrufoptionen, was eine Eigenart aller Compiler ist, nicht nur von avr-gcc. Es würde viel zu viel Arbeit machen, diese Parameter immer richtig im Terminal einzugeben. Deshalb bringt Linux das Programm make mit, das komplizierte Aufrufe erledigt, indem es die Datei makefile auswertet, die der Anwender nach bestimmten Regeln zu schreiben hat. Damit muss man sich aber nicht abgeben, wenn man Code::Blocks eingerichtet hat. Code::Blocks ist eine Cross-Compile-Plattform, die mit einer Reihe von Cross-Compilern zusammenarbeiten kann. Der avr-gcc ist einer davon. Auch Tools können generiert werden. Installation und Konfiguration der Programme avr-gcc Es handelt sich nicht um ein Programm, sondern um mehrere und eine ganze Reihe von Dateien. Alles zusammen wird auch als Toolchain bezeichnet. Es gibt viele Möglichkeiten die AVRToolchain zu installieren. Manche Pakete installieren den Compiler und den Programmer avrdude in einem Vorgang. Keine der Möglichkeiten, die ich probiert habe, war völlig problemlos, bis auf die Toolchain, die Atmel zum Download anbietet, und zwar unter http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORLINUX.aspx Weil der ATmega32 ein 8-Bit Mikrocontroller ist, habe ich Atmel AVR 8-bit Toolchain 3.4.1 - Linux 32-bit heruntergeladen. Das geht aber nicht ohne Registrierung. Man gibt Name und E-MailAdresse an und erhält eine E-Mail mit dem eigentlichen Link für den Download. Die Installationsanleitung (pdf) kann man sich ohne Registrierung ansehen. Was dann folgt, kann man kaum Installation nennen. Die heruntergeladene Datei wird in das gewählte Installationsverzeichnis verschoben (bei mir /usr/local/bin ) und dort entpackt. Das war's schon fast. Die ganze Toolchain befindet sich nun im Verzeichnis avr8-gnu-toolchain-3.4.1.798linux.any.x86 Weil mir der Name zu lang war, habe das Verzeichnis in avrtoolchain umbenannt. Die Orte von avr-gcc, von der Dokumentation und von den Header-Dateien, die beim Programmieren ggf. zu includieren sind, sollte man kennen: In /usr/local/bin/avrtoolchain/bin befindet sich avr-gcc Man muss den Pfad nicht zum Suchpfad in der Umgebungsvariablen PATH machen, wie es die Installationsanleitung fordert, wenn man ihn in Code::Blocks setzt (s.u.) In /usr/local/bin/avrtoolchain/avr/include und in drei Verzeichnissen darunter stehen die HeaderDateien, die in Programmen relativ zu diesem Pfad eingebunden werden, z.B. #include <stdio.h> oder #include <avr/pgmspace.h> . 2 Die Dokumentation ist in /usr/local/bin/avrtoolchain/doc/avr-libc/avr-libc-user-manual/index.html zu finden. Eine pdf-Datei des Manuals gibt es auch. Die Doku dürfte keine Wünsche offen lassen. avrdude Den Programmer avrdude gibt es als Paket im Ubuntu Software-Center. Die Installation ist ohne Besonderheiten. Aufgerufen wird das Programm mit /usr/bin/avrdude und einer ganzen Reihe von Optionen. Die vollständige Zusammenstellung ist im Manual enthalten, das mit man avrdude im Terminal erscheint. Die Aufrufe von avrdude, die ich brauche, habe ich in Code::Blocks als Tool konfiguriert (siehe Code::Blocks Tools). Eine ziemlich unangenehme Besonderheit hat avrdude aber doch. Nur root kann die USBSchnittstelle öffnen. Es kostet einigen Aufwand, unter dieser Restriktion mit dem Programmer zu arbeiten, denn die ganze Programmentwicklung als root zu machen kommt nicht in frage. Erst vor kurzem habe ich herausgefunden, wie das zu ändern ist. Der Editor gedit wird aufgerufen mit : gksudo gedit /etc/udev/rules.d/80usbprog.rules In die Datei 80-usbprog.rules wird der folgende Text geschrieben, und zwar in einer Zeile: ATTR{idVendor}==“03eb“, ATTR{idProduct}==“2104“, GROUP=“plugdev“, MODE=“0660“ # AVRISP mkII Dieser Text ist im wesentlichen eine Regel, die angibt, welche Gruppe von Usern mit dem AVRISP mkII arbeiten kann, wenn er in eine USB-Schnittstelle eingesteckt wird. Ob der jeweilige User Mitglied der Gruppe plugdev ist, lässt sich mit groups <username> überprüfen. Damit die Regel wirksam wird, muss udev mit sudo /etc/init.d/udev restart neu gestartet werden. Zur Sicherheit sollte man danach den USB-Stecker ziehen und wieder einstecken. Hat man einen anderen Programmer als den AVRISP mkII, kann man mit lsusb dessen Identcodes feststellen, aber auch die aller anderen eingesteckten USB-Geräte. Wahrscheinlich wegen einer Software-Aktualisierung nach der beschriebenen Änderung konnte bei mir plötzlich wieder nur root mit avrdude arbeiten. Nur eine ganz radikale Lösung hat geholfen: Ich habe meine Festplatte in zwei Partionen aufgeteilt und ein zweites Ubuntu-Linux (12.04 LTS) installiert. Dort habe ich dann avr-gcc, avrdude und Code::Blocks so eingerichtet, wie es hier beschrieben ist. Dennoch, für den Fall, dass das Problem wieder auftreten sollte, habe ich mir eine Lösung überlegt (siehe: Code::Blocks Tools / Das root / non-root Problem). Weil eine Distributionsaktualisierung bei mir noch nie völlig problemlos war, werde ich in Zukunft nur noch LTS (Long Time Support)-Updates machen, und zwar als Neuinstallation in eigener Partition. Nach und nach werde ich dann mit meinen Daten dahin „umziehen“, wodurch die alte Partition für die nächste Installation zur Verfügung steht. Code::Blocks IDE Das Paket dieser integrierten Entwicklungsumgebung ist im Ubuntu-Software-Center zu finden. Nach dem ersten Start muss man sich um die Settings kümmern. Unter Settings/Compiler and debugger/Selected compiler erscheint der GNU CC Compiler als voreingestellt. Das ist der Compiler für C-Programme, den jedes Linux mitbringt. Die von diesem Compiler übersetzten Programme laufen auf dem PC. Durch einen Klick auf das Feld rechts erscheint die Auswahlliste der anderen Compiler, mit denen Code::Blocks arbeiten kann, und da ist dann auch der GNU AVR CC Compiler dabei. Den habe ich ausgewählt und zum default Compiler erklärt. Installiert ist er bereits. Die Registerkarten im Fenster beziehen sich auf den jeweils ausgewählten Compiler. 3 Compiler settings Hier wird der verwendete Mikrocontroller markiert. Linker settings Damit die Funktionen printf() und scanf() aus der Standardbibliothek stdio.h float-Typen aus- bzw. eingeben können, müssen bei den Linker settings (am besten per copy and paste) die folgenden Options eingetragen werden : Wl,u,vfprintf lprintf_flt Wl,u,vfscanf lscanf_flt lm Man verwendet die Options nur, wenn man sie unbedingt braucht, denn ihr Ressourcenverbrauch ist hoch. Um die Options unwirksam zu machen, kenne ich bisher nur die Methode, sie aus dem Fenster zu entfernen. Search directories Hier wird der Suchpfad zu avr-gcc eingetragen, wodurch es überflüssig wird, ihn in die PATHUmgebungsvariable aufzunehmen. 4 Toolchain executables An dieser Stelle ist das Installationsverzeichnis des Compilers einzutragen, wobei vorausgesetzt wird, dass sich die auszuführenden Programme in dessen Unterverzeichnis bin befinden, was bei der AVR-Toolchain der Fall ist. Code::Blocks Tools Die Tools, die ich konfiguriert habe, sind ausschließlich Aufrufe von /usr/bin/avrdude . Die notwendigen Parameter sind bei den folgenden Beschreibungen der Tools zu finden. avrdude verlangt bei seinen Parametern die Seriennummer des Programmieradapters, die nach usb: steht und jeweils anzupassen ist. Das gilt zumindest dann, wenn der Adapter AVR ISP mkII verwendet wird. Außer pg und writefuseshex verwendet jeder Aufruf die Datei temp. Bei den Aufrufen read..... wird sie überschrieben, wenn sie im aktuellen Verzeichnis existiert, andernfalls wird sie angelegt. Der Zusatz :i bedeutet Hex-Format. pg (program) p atmega32 P usb:0200040133 c avrisp2 U flash:w:${TARGET_OUTPUT_FILE}.hex Dieses Tool wird am häufigsten verwendet. Es schreibt den Maschinencode des Programms, der nach einer erfolgreichen Compilierung in der Datei bin/Release/<project name>.elf.hex enthalten ist, in den Flash-Speicher des Mikrocontrollers. Da der Name der Hex-Datei von Projekt zu Projekt wechselt, ist ein Makro verwendet worden, der auch für den Pfad steht. 5 Die folgenden Tools werden im gleichen Fenster editiert. Makros kommen nicht vor. readflash p atmega32 P usb:0200040133 c avrisp2 U flash:r:temp:i Der Flash-Speicher des Mikrocontrollers wird in die Datei temp ausgelesen. writeflash p atmega32 P usb:0200040133 c avrisp2 U flash:w:temp:i Dieses Tool macht das gleiche wie pg. Nur ist die Datei, die verwendet wird, wiederum temp. Dadurch wird es zum Gegenstück von readflash. Das heißt, die mit readflash ausgelesenen Daten können mit writeflash zurück geschrieben werden. Das braucht man zum Beispiel, um Kopien von Mikrocontrollern herzustellen, ohne auf den Quelltext zurückzugreifen. readeeprom p atmega32 P usb:0200040133 c avrisp2 U eeprom:r:temp:i Wirkt wie readflash, nur dass der EEPROM-Speicher gelesen wird. writeeeprom p atmega32 P usb:0200040133 c avrisp2 U eeprom:w:temp:i Das Tool schreibt die mit readflash gelesenen Daten zurück. Auch dieser Vorgang gehört zum Herstellen von Kopien. 6 readhfuse und readlfuse p atmega32 P usb:0200040133 c avrisp2 U hfuse:r:temp:b p atmega32 P usb:0200040133 c avrisp2 U lfuse:r:temp:b Diese beiden Tools lesen das High-Fuse-Byte bzw. das Low-Fuse-Byte des Mikrocontrollers ATmega32 jeweils in die Datei temp. Die Fuse-Bytes enthalten die Fuse-Bits, die für grundlegende Funktionen stehen. High-Fuse-Byte ATmega32 Hex OCDEN JTAGEN CKOPT EESAVE BOOTSZ1 BOOTSZ0 BOOTRST fabrikneu 0x99 1 0 0 1 1 0 0 1 Praxis 0xC1 1 1 0 0 0 0 0 1 BODEN SU1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 Low-Fuse-Byte ATmega32 Hex BODLEVEL fabrikneu 0xE1 1 1 1 0 0 0 0 1 Praxis 0xFF 1 1 1 1 1 1 1 1 Ganz wichtig: Eine Null bedeutet, dass die mit dem Bit verbundene Funktion (siehe Datenblatt), aktiviert ist. Das Bit wird auch als programmiert bezeichnet. Die Eins bedeutet: Funktion ist deaktiviert. Das ist entgegen der Gewohnheit und hat wohl damit zu tun, dass Bits im gelöschten Flash-Speicher im Zustand 1 sind. Die Datei temp enthält beispielsweise nach dem Aufruf von readhfuse beim fabrikneuen ATmega32 die folgenden Zeichen, die denen in der vorstehenden Tabelle entsprechen: 0b10011001 Der Zusatz :b bedeutet Binär-Format, was für Kontrollzwecke am zweckmäßigsten ist. Dennoch ist die Kopie eines MC erst dann vollständig, wenn auch die Fuse-Bytes kopiert wurden. writefuseshex p atmega32 P usb:0200040133 c avrisp2 u U hfuse:w:0xC1:m U lfuse:w:0xFF:m Der Aufruf schreibt die Fuse-Bytes, diesmal allerdings nicht aus einer Datei. Die Hex-Bytes sind Parameter, hier C1 und FF. Diese beiden Werte habe ich bisher immer verwendet (siehe auch die Zeile Praxis in der obigen Tabelle). Im High-Byte deaktiviere ich das JTAG-Interface und schütze den EEPROM gegen Löschen. Im Low-Byte stelle ich die Taktquelle ein, die bei mir ein externer 16 MHz-Quarz ist. Fehler sollte man keine machen, insbesondere muss man die eingestellte Taktquelle auch verwenden, sonst läuft nichts, auch nicht das Lesen und Schreiben der Fuse-Bytes. Dumm, wenn man nicht mehr weiß, welche Taktquelle im Fuse-Byte eingetragen ist. Ich kann mir vorstellen, dass mit Ausprobieren aller Taktquellen, die in frage kommen könnten, das Problem zu lösen ist. Dieses Tool irrtümlich anzuklicken, wäre also fatal. Weil das sehr leicht passieren kann, habe ich einen Fehler in den Aufruf eingebaut ( /usr/bin/avrdu ), der zuerst korrigiert werden muss. Dieser Ersatz für eine Bestätigungsabfrage stört nicht weiter, da das Tool sehr selten gebraucht wird. 7 Das root / non-root-Problem Sollte der Fall eintreten, dass plötzlich nur noch root mit avrdude arbeiten kann (siehe avrdude oben), sind die Tools nicht mehr brauchbar. Mit der folgenden Notlösung kann die Arbeit jedoch fortgesetzt werden: Terminal öffnen und mit sudo -s -h root werden. Dann wird der Aufruf /usr/bin/avrdude in die Kommandozeile geschrieben. Die Parameter des jeweils auszuführenden Tools überträgt man am besten mit copy and paste. Beim Tool pg ist der Makro durch den Pfad/Namen der Hex-Datei zu ersetzen, z.B. bin/Release/demo.elf.hex Das Terminal bleibt geöffnet. Mit der Auf- und Ab-Taste kann man durch die zurückliegenden Aufrufe scrollen, auch wenn der Rechner zwischenzeitlich ausgeschaltet wurde. Wiederholte Aufrufe müssen also nur gesucht und nicht von Hand eingegeben werden. Arbeiten mit Code::Blocks Man eröffnet ein neues Projekt, indem man ein Muster dafür auswählt, z.B. das AVR Projekt. Der Projektname, der vergeben werden muss, wird für die Projektdatei *.cbp , aber auch für das Projektverzeichnis verwendet, das gleichzeitig Arbeitsverzeichnis ist. Es enthält nach der Projekterzeugung ein leeres Hauptprogramm main.c Eigene Quellcode-Dateien werden in das Arbeitsverzeichnis kopiert oder im Editor geöffnet und mit save as dorthin gespeichert. Unter Project / Add Files werden Quellcode- und Header-Dateien explizit dem Projekt zugefügt. Dann kann der jedem Programmierer bekannte Arbeitszyklus beginnen. Sehr vorteilhaft finde ich in Code::Blocks die Suchfunktion über mehrere Dateien hinweg und die Möglichkeit, sich Deklarationen und Implementationen anzeigen zu lassen und dorthin zu wechseln. Nur die Shortcuts, die ich gerne den Tools zuordnen würde, vermisse ich. 8
© Copyright 2024 ExpyDoc