2013-01-11

ArduinoISP - AVR Chips programmieren

Ich wollte erst mal klein anfangen und schauen, ob die zusätzlichen Mikrocontroller, die ich bestellt habe auch funktionieren. Dazu reicht mir ein "Hello World", sprich das minimale "Blink"-Programm des Arduino IDE (übrigens: 1.0.3), um eine LED dann zum Blinken zu bringen.
Zusätzliche Elemente, wie z.B. einen Quartz wollte ich mir nach Möglichkeit ersparen.

Arduino als ISP (und als "Taktgeber"!)
Doch zunächst muss man die Chips zum Programmieren vorbereiten und einen ISP-Programmer (In-System-Programmer) braucht es auch noch.
Ersteren erhält man, in dem man das existierende Arduino-Board (UNO, Duemilanove, etc.) als Programmiergerät verwendet.
Beschrieben wird dies im Detail hier: http://arduino.cc/en/Tutorial/ArduinoISP

Es wird ein entsprechendes Programm "ArduinoISP" auf das Board geladen und danach verhält sich das Board gegenüber dem Arduino IDE bzw. avrdude wie ein Programmiergerät (genauer: "stk500"), so lange, bis man ein anderes Programm läd, also Vorsicht bei den folgenden Uploads :-)

Verfeinerung: Ich will es gleich vorweg nehmen, nicht alle Versuche waren sofort erfolgreich. 
Um sich den Ärger gleich zu sparen, nimmt man am Besten gleich die Weiterentwicklung des ArduinoISP, den ArduinoISP2


“This is a fork of Adafruit's ArduinoISP which is a fork of Arduino's ArduinoISP which adds an 8 MHZ 'crystal' output on pin #9 so you don't need an extra oscillator/crystal. Can also rescue some bricked chips with bad oscillator fuses”

Diese Version ist von der, die beim IDE mitgeliefert ist kaum zu unterscheiden (vermutlich ist es auch nur eine Frage der Zeit). Bis dahin: Wenn man im passenden Sourcecode nachschaut, sollte man diese Zeilen finden:
  // setup high freq PWM on pin 9 (timer 1) 
// 50% duty cycle -> 8 MHz
Dies ist extrem nützlich. Hat man nämlich beim Experimentieren einen Chip auf einen externen Taktgeber eingestellt (ggf. ist dies sogar die Werkseinstellung?), müsste man zum Programmieren im Setup eben auch wie im Tutorial ersichtlich einen Quartz und zwei Kondensatoren verbauen.
Denn sobald beim Initialisieren der Chips die sogenannten "Fuse-Bits" gesetzt werden und diese neben der Taktfrequenz auch die Verwendung eines externer Taktgeber definieren, reagiert der Chip nicht mehr ohne auf weitere Programmierversuche.

Die Spezialversion des ArduinoISP liefert immerhin einen 8Mhz Taktgenerator, der dieses Problem elegant umschifft (Pin 9 des Arduino Boards an XTAL1 des Chips anlegen).
Selbst wenn der Chip für 16Mhz konfiguriert wurde, sollte dies funktionieren.
Sonst gibt es hier noch eine nette Abhandlung zu den "Fuses" und zum Troubleshooting (wie man Chips retten kann, die man falsch programmiert hat): http://www.gammon.com.au/forum/?id=11643
Die offizielle Troubleshooting-Seite des Arduino hat mir bislang noch wenig geholfen.


When you buy a brand new, blank ATmega328p, it comes with a set of fuses (basically hardware settings) which give it maximum reliability, but they aren't the default that is required for the chip to work with the Arduino IDE and libraries.  In order to burn the correct fuses onto it, run the following command (this assumes that you're using Arduino-as-ISP on COM4);


avrdude -pm328p -cstk500v1 -b19200 -PCOM4 -v -C ..\etc\avrdude.conf -U lfuse:w:0xFF:m -U hfuse:w:0xD6:m -U efuse:w:0x05:m -B250

Diese Zeile dient nur zur Illustration. Man kann im IDE unter Einstellungen den Upload ausführlicher ausgeben lassen. Dann erhält man auch die avrdude Kommandozeile. Der -B Parameter passt das Timing beim Programmieren an. Ggf. ein Tipp, der hilft, wenn alles verloren scheint. Oder eben doch ein Setup mit externen Quartz?

Aber damit genug zum Exkurs. Im Folgenden setze ich den ArduinoISP2 einfach voraus :-)
So kompliziert ist es gar nicht. Der erste Versuch war eben etwas steinig. Bis es lief - daher diese Tipps zuerst - damit ich mich beim nächsten Mal darauf stützen kann, wenn es klemmt.


Verkabelung - Ready to Program:

Auch hier wieder nur eine kleine Zusammenfassung der zahlreichen Versuche und Tipps, die ich ausprobiert habe, bis es klappte (habs gerade neu gezeichnet):

Das Bild sollte an sich eine gute Referenz sein und selbsterklärend (beim Verkabeln besser doppelt prüfen, dass man den richtigen Pin erwischt hat!).
Das macht übrigens richtig Spass mit dem Experimentierboard und ein paar vorkonfigurierten "Strippen", die sich leicht stecken lassen. Einen extra Programmer brauche ich vorerst nicht.

Neben dem zusätzlichen Clock-Signal von Pin D9 des Boards an XTAL1, muss man beim Thema Reset ggf. noch etwas nachbessern:

Slave-Chip (der zu programmierende Chip auf dem Experimentierboard):
Der Reset-Pin (Chip Pin 1?) kann optional mit einem Pull-Up Widerstand (1kOhm; braun-schwarz-rot-gold) an die Versorgungsspannung geführt werden.


Damit das Arduino-Board selbst nicht während dem Programmieren resettet wird (durch seine USB bzw. Serielle Verbindung), muss man dies ggf. unterbinden:
Beim UNO wohl durch einen 10 µF Kondensator (ELKO), dessen Minus-Pol an GND geht, die Plus-Seite an den Reset-Pin des Boards.
Ich habe beim Arduino Duemilanove stattdessen mit einem 110 Ohm Pullup Erfolg gehabt (aus 2 parallelen 220Ohm Widerständen.
!!! Diese Schaltung wieder entfernen, wenn man ein neues Programm auf das Board selbst laden will !!!

Wie gesagt: Bin mir nicht ganz sicher, welche davon es am Ende effektiv gebraucht hat. Der 1k Pullup am Slave-Chip war eher nicht erforderlich.

Bootloader Programmieren:
Letztlich ist dies nun gaaanz einfach: Man wählt im IDE die entsprechenden Einstellungen:

["ArduinoISP" Programm auf das Board geladen?]
Board:  "Arduino Duemilanove w/ ATmega328 - Optiboot" [siehe unten]
Port:  COM
Programmer: Arduino as ISP


Dann "Bootloader installieren" wählen und der Ausgabe gebannt folgen :-)

Warnung: Die Einstellung von "Board" ist hier extrem heikel! Sie bestimmt nun das Target-Board NICHT der Programmierer (der wird durch COM-Port und "Arduino as ISP" hinreichend beschrieben).
Beim "Board" sollte man aufpassen. Es steuert nicht nur, für welchen Target-Prozessor die Programme compiliert werden (insbes. Pins und Taktfrequenz), sondern auch, welche Fuses gesetzt werden und welcher Bootloader gebrannt wird.
Hier schliesst sich der Kreis: Wenn man hier daneben liegt, hilft der Trick mit dem Taktgeber oben hoffentlich weiter :-)

Arduino Duemilanove updaten:

Der Duemilanove ist fast baugleich mit dem UNO, insbesondere neuere Fassungen des Duemilanove haben einen ATMega 328 (statt 168). Der Bootloader des UNO ist allerdings etwas schlanker und schneller (Stichwort "Optiboot"):

Upgrade your Arduino for free with Optiboot   http://code.google.com/p/optiboot/Optiboot is an easy to install upgrade to the Arduino bootloader within Arduino boards. It provides the following features:
  • Allows larger sketches. Optiboot is a quarter of the size of the default bootloader, freeing 1.5k of extra space.
  • Makes your sketches upload faster. Optiboot operates at higher baud rates and has streamlined programming.
  • Adaboot performance improvements. Optiboot runs your sketches sooner, with no watchdog issues.
  • Compatible with 168 and 328 Arduinos including Lilypad, Pro, Nano
Die Idee für den Upgrade hatten schon andere vor mir:

Es passt hier aber eben gut her, deshalb kurz zusammengefasst:
Man könnte einfach den Board-Eintrag für das UNO nehmen. Ich habe mich entschieden, den Eintrag für das Duemilanove mit Optiboot zu ergänzen:

In der Datei arduino-1.0.3\hardware\arduino\boards.txt wird folgender Eintrag ergänzt:

##############################################################

Duemilanove.name=Arduino Duemilanove w/ ATmega328 - Optiboot

Duemilanove.upload.protocol=arduino
Duemilanove.upload.maximum_size=32256
Duemilanove.upload.speed=115200

Duemilanove.bootloader.low_fuses=0xFF
Duemilanove.bootloader.high_fuses=0xDE
Duemilanove.bootloader.extended_fuses=0x05
Duemilanove.bootloader.path=optiboot
Duemilanove.bootloader.file=optiboot_atmega328.hex
Duemilanove.bootloader.unlock_bits=0x3F
Duemilanove.bootloader.lock_bits=0x0F
Duemilanove.build.mcu=atmega328p
Duemilanove.build.f_cpu=16000000L
Duemilanove.build.core=arduino
Duemilanove.build.variant=standard


Damit der Eintrag wirksam wird, muss man das IDE wie gewohnt neu starten.
Der Bootloader wird dann über ArduinoISP gebrannt, die Einträge "protocol" und "speed" beziehen sich auf die Uploads der Programme später im Betrieb.

Generell habe ich die Liste der angebotenen Boards etwas ausgedünnt. Im nächsten Post beschreibe ich, wie man zusätzliche Chips in die Liste der Boards aufnimmt. Spätestens dann wird es unübersichtlich :-)

Hier sieht man schon ein paar Teile für den nächsten Aufbau :-)




















Nach der erfolgreichen Programmierung des Bootloaders, kann man den neuen Chip in den Duemilanove einsetzen. Dazu vorsichtig den Original-Chip aus dem Sockel hebeln und den frisch programmierten Chip in die Fassung einbauen. Dann mal ein Beispielprogramm laden, z.B. "ArduinoISP2".[Die Autoreset-Schaltung nicht vergessen - die müsste man nun abklemmen!!]
Der ausgebaute ATMega 328 kann dann sogleich auch einen Optiboot erhalten. Im schlimmsten Fall ist er so ein prima Ersatzchip sowohl für einen UNO als auch für den Duemilanove, wenn doch mal was beim Verkabeln schief geht.


Ein paar Extras

Nick Gammon hat ein paar interessante Programme ("Sketches") im Zusammenhang mit der AVR Programmierung zur Verfügung gestellt: https://github.com/nickgammon/arduino_sketches/archive/master.zip

http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123
http://www.gammon.com.au/forum/?id=11637
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11635


Insbesondere diese zwei:
  • Atmega_Board_Detector - Liest ein paar Infos des angeschlossenen Chips aus, Typ, gesetzte Fuse-Bits, Bootloader,etc. 
  • Atmega_Board_Programmer - Damit wird das Arduino Board zum unabhängigen Programmer - er erkennt den angeschlossenen Chip und installiert einen Bootloader - Massenprogrammierung nach einem Grosseinkauf?

Für künftige Spezialfälle: Web-based fuse calculator http://www.engbedded.com/fusecalc

Noch zwei:

TinyDebugKnockBang - Serial like debugging for processors with an   uncalibrated / inaccurate clock.


  TinyISP 1.0 - Turn an ATmega328[P] Arduino compatible board (like an Uno) or
  a Teensy into an In System Programmer (ISP).  Based on MegaISP and
  ArduinoISP.






Keine Kommentare:

Kommentar veröffentlichen