zurück zum Artikel

Microcontroller flashen: Arduino Uno als In-System-Programmer

Hintergrund
Arduino Uno als Programmer für PIC

Die Arduino-Plattform hat sich in der Bastlerszene unter anderem auch deshalb durchgesetzt, weil man keine speziellen Adapter benötigt, um ein Programm in den Flash-Speicher des Mikrocontrollers zu schreiben. Praktischerweise lässt sich der Arduino sogar selbst als Universal-Programmieradapter nutzen, um einzelne Mikrocontroller wie AVRs und PICs zu flashen.

Zutaten:

Ein Arduino [1] eignet sich fürs Prototyping bestens. Mit mehr als 20 Euro ist der stationäre Einsatz in einer Schaltung allerdings nicht ganz billig, vor allem wenn ein ATmega für ein paar Euro und ein paar weitere Bauteile ausreichen würden. Während beim Arduino der Bootloader über die herkömmliche serielle Schnittstelle (via USB2Serial-Wandler) mit einem PC spricht, programmiert man einen "nackten" ATmega in der Regel direkt "In System" über sein Serial Peripheral Interface (SPI). Ein normaler PC unterstützt zwar die normale asynchrone, serielle RS232-Schnittstelle, jedoch nicht die synchrone SPI. Deshalb benötigt man einen Übersetzer – einen Programmer. Die Bandbreite reicht dabei von billigen Modellen wie den USBasp über den "AVR ISP" bis hin zu ganzen Evaluierungsboards wie dem STK500 beziehungsweise STK600.

Die Arduino-IDE unterstützt verschiedene externe Programmer. Auch der USBasp findet sich neben dem hauseigenen ArduinoISP.

Zum Flashen des Controller-Speichers arbeitet der externe Programmer als sogenannter Master, der den Atmel-Prozessor (Slave) steuert. Über die Reset-Leitung RST (Low) bringt er den Atmel in den programmierbereiten Zustand. Den Takt für die Datenübertragung gibt der Master über die Leitung SCK vor. Über die Leitung MOSI (Master Out, Slave in) sendet er Befehle an den Slave, die in der Regel aus vier Bytes bestehen. Das erste Byte signalisiert die gewünschte Operation und den Zielspeicher, etwa ob in das Flash oder das EEPROM geschrieben werden soll. Die Bytes zwei und drei enthalten die Speicheradresse; zuletzt kommt das Datenbyte.

Die Arduino-IDE bringt in den Beispielen bereits den Sketch für ArduinoISP mit. Den muss man zuerst per Upload in der Arduino übertragen.

Über die Leitung MISO (Master In, Slave Out) kann der Programmer hingegen nach Übermittlung des passenden Befehls Daten auslesen. Zwischen den Operationen sind gewisse Pausen einzuhalten. Genauere Details zum Ablauf beschreibt Atmel in seiner frei verfügbaren Application Note AVR910 [PDF [2]]. Diese haben die Arduino-Entwickler genutzt, um mit ihren Boards einen AVR-Programmer nachzubilden. Auf diese Weise kann man im ersten Schritt mit einem Arduino sein Programm austesten und im zweiten Schritt denselben Arduino (mit einem anderen Sketch) nutzen, um das Programm in einen externen ATmega zu brennen.

Fremdgänger

Für die Steuerung von MISO, MOSI und SCK dienen beim Arduino UNO die Pins 11, 12 und 13, den RST-Eingang des Mikrocontrollers steuert Pin 10. Die klassische Belegung eines sechspoligen ISP-Wannensteckers zum Programmieren eines AVR-Controllers in einer fertigen Schaltung ist im Bild rechts zu sehen. Auf einem Steckbrett würde die Verkabelung wie auf dem Bild darunter aussehen.

Die Belegung 6-poliger und 10-poliger ISP-Anschlüsse für Atmel-Controller sind standardisiert.

Der unter dem Menüpunkt Beispiele verfügbare Sketch ArduinoISP steuert die Pins gemäß der Spezifizierung von Atmel. Der Sketch wird über die normale Upload-Funktion auf den Arduino gebracht. Beim Arduino Uno muss man für die weiteren Schritte einen Kondensator (Elko mit 10µF) zwischen GND und Reset legen. Er fängt den Reset-Impuls (Low) ab, den der USB-Seriell-Wandler auf dem Board des Arduino Uno beim Starten der seriellen Kommunikation sendet. Der Reset-Impuls führt nämlich dazu, dass der Mikrocontroller auf dem Arduino-Board seinen Bootloader zur Neuprogrammierung startet, statt den Arduino-Sketch zu starten.

Ein paar Leitungen genügen zum Flashen eines AVR-Controllers.

Das Arduino-Board arbeitet jetzt selbst als Programmer. Wie kommen damit nun die eigenen Programme auf einen neu zu flashenden Controller? Praktischerweise unterstützt die Arduino-IDE selbst die Ansteuerung eines als ISP-Programmer arbeitenden Arduinos. Unter dem Menüpunkt Tools wählt man als Programmer "ArduinoISP" aus. Um einen übersetzten Sketch über den ArduinoISP-Programmer zu übertragen, muss man vor dem Klick auf den Upload-Button zusätzlich die Shift-Taste drücken.

Leider funktioniert dieser einfache Weg nur mit Programmen, die man innerhalb der Arduino-IDE erstellt hat. Mit anderen Compilern oder IDEs erstellte Binär-Dateien (in der Regel Hex-Dateien) lassen sich nicht über die Upload-Funktion der Arduino-IDE auf einen Controller hochladen. Dafür bietet sich das Open-Source-Tool Avrdude [3] an. Es ist ein Werkzeug für die Befehlszeile.

Mit dem Befehl

avrdude -c avrisp -p atmega8 -P COM5 -b 19200 -U flash:w:main.hex 
Avrdude prüft automatisch, ob der Flash-Vorgang erfolgreich war.

schreibt (:w) man die Hex-Datei main.hex via ArduinoISP (-c avrisp) am (virtuellen) COM-Port 5 in den Programm-Speicher (-U flash) eines ATmega8. Avrdude prüft den Erfolg des Vorgangs, indem er den Speicher anschließend ausliest und mit der vorgegebenen HEX-Datei vergleicht. Möchte man Werte aus der Datei eeprom.hex in den EEPROM schreiben, gibt man als Parameter -U eeprom:w:eeprom.hex an.

Damit ein Quarz am Oszillator anschwingt, muss man zwei Keramikkondensatoren à 22pF anschließen.

Mit der simplen Beschaltung wie im Bild oben funktioniert es freilich nur, wenn der ATmega frisch aus dem Regal stammt. Dann nämlich sind seine sogenannten Fuses auf eine interne Takterzeugung eingestellt und der Mikrocontroller beginnt, beim Anlegen der Versorgungsspannung zu arbeiten. Ansonsten muss man keine weiteren Einstellungen ändern oder Fuses aktivieren.

Ist der Controller jedoch bereits für einen Quarz oder eine externe Taktquelle eingestellt, muss man diese zusätzlich zur Verfügung stellen. Die Beschaltung mit einem Quarz ist im Bild rechts zu sehen. Auch wenn die eingestellte Taktrate von 1 MHz nicht ausreicht, muss man Hand anlegen. Dazu muss man sich allerdings mit den Fuses auskennen.

Tipp

Der Leonardo lässt sich auf ähnliche Weise zum Programmer umfunktionieren. Allerdings muss man dazu andere Pins auf dem Board verkabeln und den Sketch ArduinoISP anpassen. Im Netz [4] gibt es eine Anleitung, die zusätzlich zeigt, wie man ATTinys in die Arduino-IDE einbindet.

Sicherungen

Die falsche Auswahl der Taktquelle ist übrigens eine der häufigsten Fehler, um sich mit seinem Programmer aus dem Controller auszusperren. Welchen Takt der Controller benutzt oder wie er ihn erzeugt, legen sogenannte Fuses fest. Eigentlich sind es keine Fuses, da nichts durchbrennt und man sie immer wieder umprogrammieren kann.

Die vier Fuses CKSEL0 bis CKSEL3 stellen ein, ob ein interner oder externer Oszillator zum Zuge kommen oder ein Quarz benutzt wird. Die Übersicht auf Seite 142 zeigt die Möglichkeiten. Zu Verwechslungen bei der Konfiguration kommt es immer wieder, weil bei den AVR-Controllern die Fuses als Low-Aktiv umgesetzt sind. Eine 0 bedeutet, dass die Funktion aktiviert ist, eine 1 heißt "ausgeschaltet".

Mit der Fuse CKDIV8 (Clock Divide) teilt man den anliegenden respektive erzeugten Takt durch 8, standardmäßig ist die Fuse aktiv. Mit CKOUT (Clock Out) lässt sich der Takt auf einen Pin von PORTB ausgeben, auf welchen Pin genau, steht im Datenblatt des jeweils verwendeten Modells. Mit den beiden Flags SUT0 und SUT1 (Start Up Time) stellt man die Wartezeit ein, nach der die CPU nach dem Einschalten oder einem Reset den ersten Befehl ausführt. Die Wartezeit soll sicherstellen, dass ein externer Quarz oder Resonator beziehungsweise der interne Oszillator richtig angeschwungen sind, um einen stabilen Takt zu liefern.

Daneben gibt es weitere Fuses, wobei nicht jede Fuse in allen AVR-Controllern vorhanden ist. Auch die konkrete Funktion kann abhängig vom Modell variieren. Praktischerweise helfen Online-Fuse-Rechner beim Austüfteln der richtigen Einstellungen für das gewünschte Produkt, beispielsweise der Engbedded Atmel AVR Fuse Calculator [5], der die zwei Fuses-Bytes (Hi und Lo) als Parameter für Avrdude ausgibt, etwa

-U lfuse:w:0xf1:m -U hfuse:w:0xdd:m< 

Zudem gibt es Apps für Android und iPhone, die das offline erledigen.

Um die Fuses im Mikrocontroller zu setzen, benutzt man ebenfalls Avrdude. Die Zeile

avrdude -c avrisp -p atmega8 -P COM5 -b 19200 -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m 

setzt die beiden Fuses. Durch die Formatangaben :m am Ende der jeweiligen Fuses weiß Avrdude, dass er die Angaben direkt aus der Befehlszeile übernehmen soll, statt sie aus einer Datei zu lesen.

Neben der fehlerhaften Wahl der Taktquelle bieten die Fuses RSTDISBL, SPIEN und DWEN das größte Gefährdungspotenzial, seinen Mikrocontroller zu bricken, also in einen wertlosen Klumpen Plastik zu verwandeln.

RSTDISBL steht für Reset Disable und trennt den Mikrocontroller intern vom Reset-Pfad ab, um den Reset-Pin als I/O-Pin freizugeben. Das hat etwa bei den achtbeinigen ATTinys den Vorteil, dass man im Betrieb einen Pin mehr zur Verfügung hat, allerdings lässt sich der Chip dann nicht mehr via ISP flashen. Ganz auf verlorenem Posten steht man dann aber doch nicht, sofern man einen STK500-Programmer sein Eigen nennt. Damit ist nämlich das sogenannten High Voltage Programming (HVP) möglich, das die AVR-Controller neben der In-System-Programmierung (ISP) zusätzlich unterstützen. HVP funktioniert allerdings nur, wenn man den IC in einen Sockel des STK500 einstecken kann. Ist er fest in einer Schaltung eingebaut, war’s das.

SPIEN bedeutet SPI Enable, also ob sich der Controller via SPI flashen lässt. Ist die Fuse nicht aktiv, kann man den IC nur noch via HVP retten. DWEN aktiviert die debugWIRE-Schnittstelle bei jüngeren AVR-Controllern. Dann wird ISP jedoch deaktiviert. Zurückschalten kann man nur noch über HVP oder die debugWIRE-Schnittstelle selbst – wofür man jedoch einen Debugging-Adapter wie JTAGICE mkII benötigt.

Mit diesen Einstellungen arbeitet ein ATTiny45 mit 16 MHz intern erzeugtem Takt und einer Brown-Out-Detection bei 2,7V (-U lfuse:w:0xe1:m -U hfuse:w:0xdd:m).

Mit den Fuses BOOTSZ1 und BOOTSZ0 (Bootsize) legt man die Größe des Bootbereichs und daraus resultierend die Startadresse des Bootloaders fest. Welche Kombinationen damit möglich sind, zeigt die Tabelle oben exemplarisch für den ATmega328. Die Größe des Bereichs variiert von Modell zu Modell und ist im jeweiligen Datenblatt angegeben. Damit bei einem Reset beziehungsweise einem Power-Up der Programmzähler statt auf Adresse 0xc00 auf den Bootloader zeigt, muss BOOTRST aktiv sein.

Notiz

Die meisten ATmegas laufen standardmäßig mit 1 MHz internem Takt. Er ergibt sich aus der Frequenz des internen RC-Oszillators mit 8 MHz und der gesetzten Fuse CKDIV8.

Die Brown-Out-Detection (BOD) reagiert auf Spannungsabfälle der Stromversorgung, die die CPU in einen undefinierten Zustand bringen können. Ist jedoch die Fuse BODEN (Brown Out Detection Enable) aktiv, löst der Abfall unter der mit BODENLEVEL1 bis BODENLEVEL3 definierten Spannung einen Reset aus. Nutzt man einen Bootloader oder das EEPROM, lautet die Empfehlung von Atmel, einen Reset ab 2,7V (BODLEVEL=101) auszulösen, da es sonst zu gelöschten oder überschriebenen Speicherstellen kommen kann.

Daneben gibt es noch diverse weitere Fuses, an denen Hobbyprogrammierer in der Regel aber nichts ändern müssen. Dazu gehören die Watchdog-Fuse WDTON zum Aktivieren des Watchdog-Timers, EESAVE zum Schutz des EEPROM vor Lösch-Befehlen. SELFPRGEN erlaubt der Firmware, selbst Daten oder neuen Programmcode in den Flash-Speicher zu schreiben. AVR-Controllern mit Bootloader-Unterstützung fehlt dies Fuse, weil die Reprogrammierfunktion der Bootloader erledigt – beispielsweise bei Arduino. Sogenannte Lockbits (LBx, BLBxy) verhindern das Auslesen von Flash und EEPROM oder das Überschreiben des Bootloaders.

Tipp

Das leicht zu bedienende Tool Xloader [6] flasht HEX-Dateien in Arduino-Boards ohne Zuhilfenahme der Arduino-IDE. Damit kann man sein Kompilat für Arduino weitergeben, ohne den Quellcode veröffentlichen zu müssen. Xtool setzt auf Avrdude auf.

PICs programmieren

Im Unterschied zu AVR-Controllern bieten PICs keine SPI-Schnittstelle zur Programmierung.

Ein Arduino Uno eignet sich auch für die Programmierung von Mikrocontrollern anderer Hersteller, beispielsweise der PIC-Serie von Microchip. Der Entwickler Rhys Weatherley hat die Sketches PIC_Program und PIC_Program_EEPROM für den Arduino [7] entwickelt, mit denen sich jeweils Flash und EEPROM beispielsweise eines PIC 16F628A programmieren lassen.

Anders als bei AVR-Controllern erwarten PIC-Controller eine zusätzliche Programmierspannung, die zwischen 10,5V und 13,5V liegen sollte. Die Spannung lässt sich über ein Labornetzteil oder ein Steckernetzteil zuführen.

Arduino Uno als Programmer für PIC
Die komplette Schaltung des PIC-Programmers ist mit einem Arduino schnell aufgebaut. Neben den Drahtbrücken benötigt man nur einen Widerstand von 330 Ohm.

Kompakter geht es mit Aufwärtswandlern, die aus den 5 Volt des Arduino 12 Volt machen. Traco bietet solche Wandler als fertige Module (TMA 0512D, ab 5 Euro) an, Bastler bauen sich aus einem Schmitt-Trigger-IC, ein paar Schottky-Dioden und Kondensatoren eine Ladungspumpe diskret auf (siehe Bild).

Mit einer Spannungsverdopplerschaltung lässt sich die 5V-Spannung des Arduinos bis auf 12V erhöhen. Maximal kann die Schaltung 10mA Strom liefern – zum Programmieren reicht das allemal.

Wie bei ArduinoISP benötigt man noch ein Programm zur Steuerung des Programmmers und zum Übertragen seiner Hex-Datei. Weatherly stellt dafür das Tool Ardpicprog [8] für die Befehlszeile als Source-Code zur Verfügung. Unser Autor Ulrich Schmerold bietet für Windows alternativ das grafische Toll Arduino Pic Programmer (ArdPicProgHost) [9] an, das ebenfalls im Quellcode, aber auch als bereits ausführbares Programm zum Download zur Verfügung steht.

Fazit

Im Grunde sind die Fuses der AVR-Controller relativ leicht zu verstehen. Die inverse Bedeutung der Fuses verwirrt jedoch viele Anwender erfahrungsgemäß, weshalb wir Tools zum "Ausrechnen" empfehlen. Auf jeden Fall sollte man die Finger von RSTDISBL, SPIEN und DWEN lassen – standardmäßig sind sie nicht gesetzt und in allen Berechnungstools als inaktiv vorbelegt. Bei der falschen Wahl der Taktquelle kann man sich oft mit zusätzlicher Beschaltung behelfen. (dab [10])

Frequenztricksereien

Einige AVR-Projekte setzen auf eine interne Takterzeugung von 16,5 MHz. Das funktioniert nur in neueren Modellen, die mittels einer internen PLL den Takt des internen RC-Oszillators vervielfachen können. Beim ATTiny liegt der Takt des Oszillators bei 8 MHz, aus dem die PLL-Schaltung einen Takt von 64 MHz ableitet. Das Ganze wird wieder durch vier geteilt, womit dem Prozessor 16 MHz zur Verfügung gestellt werden.

Wie kommt man nun auf einen Takt von 16,5 MHz? Diesen erreicht man durch Verstellen des RC-Oszillators über das Register OSCCAL. Der Hersteller nutzt es, um die Oszillatoren ab Werk auf 8 MHz zu kalibieren. Man kann es jedoch auch selbst beschreiben und so die Frequenz verändern.

Die USB-Implementierung "V-USB" für AVR-Controller macht beispielsweise von dieser Möglichkeit Gebrauch, um den Takt im Betrieb hochzufahren und sich der USB-Geschwindigkeit anzupassen. Mehr als 8,8 MHz empfiehlt der Hersteller Atmel jedoch nicht, da dann beim Zugriff auf das Flash und das EEPROM Probleme auftreten können.


URL dieses Artikels:
http://www.heise.de/-2769246

Links in diesem Artikel:
[1] http://www.heise.de/thema/Arduino
[2] http://www.atmel.com/images/doc0943.pdf
[3] http://www.nongnu.org/avrdude/
[4] http://www.correderajorge.es/the-powerful-attiny-arduino/
[5] http://www.engbedded.com/fusecalc
[6] http://www.hobbytronics.co.uk/arduino-xloader
[7] http://rweather.github.io/ardpicprog/
[8] http://rweather.github.io/ardpicprog/
[9] http://www.pikoder.com/ArdPicProg_Download_DE.htm
[10] mailto:dab@ct.de
[11] http://www.heise.de/make/inhalt/2014/1/138/