Titelbild: Clker-Free-Vector-Images auf Pixabay

Eines der verwirrendsten Dinge, vor allem für Neulinge, sind die AVR-Fuses. Schlimmer noch, wenn man die falschen Fuse Bits setzt, kann man seine MCU „bricken“, d.h. die MCU in einen „Ziegelstein“ zu verwandeln, der zu nichts mehr zu gebrauchen ist. In diesem Blog-Beitrag werde ich Werkzeuge vorstellen, die helfen, die Fuse-Bits richtig zu setzen. Und wenn es hart auf hart kommt, d.h. die falschen Fuses gesetzt wurden, werde ich Möglichkeiten aufzeigen, mit denen man die MCUs wieder zum Leben erwecken kann.

Wofür braucht man Fuses?

Die Fuse-Bits der AVR-MCUs steuern eine Menge wichtiger Parameter der MCU:

  • Soll der Systemtakt durch 8 geteilt werden?
  • Gibt es einen Bootloader?
  • Wie groß ist der Bootloader?
  • Soll es einen Brownout-Reset geben?
  • Bei welchem Spannungspegel soll der Brownout-Reset erfolgen?
  • Soll das MCU-Taktsignal auf einen Pin geleitet werden?
  • Soll das EEPROM erhalten bleiben, wenn der Flash-Speicher umprogrammiert wird?

All diese Parameter sind wichtig, führen aber nie zu einem Bricking der MCU. Anders verhält es sich mit dem Parameter Taktquelle. Hier kann man den internen Oszillator, einen externen Oszillator oder einen externen Quarz wählen. Wenn man nicht den internen Oszillator wählt, benötigt man eine externe Taktquelle oder einen Quarz, um mit der MCU zu kommunizieren. Andernfalls ist man „ausgesperrt“.

Es gibt noch weitere „kritische“ Fuse-Bits, die einen „aussperren“ können:

  • Reset disabled: Wenn dieses Fuse-Bit programmiert ist, wird der RESET-Pin zu einem normalen Ein-/Ausgangs-Pin. Die ISP-Programmierung ist auf die RESET-Leitung angewiesen. Mit einem ISP-Programmer kann man dies nicht rückgängig machen.
  • debugWIRE enabled: Die RESET-Leitung wird als serielle Halbduplex-Verbindung zur On-Chip-Debugging-Hardware der MCU verwendet. Dies bedeutet, dass ein ISP-Programmierer nicht mehr auf die MCU zugreifen kann. Der Debugger sollte in der Lage sein, diese Fuse zu deaktivieren.
  • Serial program downloading (SPI) enabled: Diese Fuse ist normalerweise aktiviert und wird benötigt, um Programme auf die MCU zu laden. Wenn dieses Fuse-Bit unprogrammiert ist, dann kann man keinen Code mehr mit dem ISP-Programmierer hochladen.

Wenn eines dieser drei Fuse-Bits den falschen Wert hat, dann kann man die MCU nicht mehr programmieren und auch die Fuses nicht mehr mit einem normalen ISP-Programmiergerät ändern. Der Chip ist „gebricked“. Was man jetzt braucht, ist ein spezieller Hochspannungs-Programmer. Ich werde am Ende dieses Blogposts darauf eingehen, wie man sich solch einen Programmer auf einem Steckbrett selber bauen kann.

Übrigens programmiert man ein Fuse-Bit, indem man es auf null setzt. Der unprogrammierte Status ist die Eins.

Fuses lesen und schreiben

Wenn man mit der Arduino-IDE arbeitet und die Boards über die serielle Verbindung programmiert, muss man sich nicht mit Fuses befassen. Und tatsächlich kann man auch keine Fuses über die serielle Schnittstelle ändern.

Dafür benötigt man einen zusätzlichen ISP-Programmer, der an die Zielplatine angeschlossen werden muss, um Fuses ändern zu können. Eine (billige) Möglichkeit besteht darin, einen Arduino Uno in einen ISP-Programmer zu verwandeln, was auf der Arduino-Website ausführlich beschrieben wird. Sudar Muthu hat in einem Blogbeitrag beschrieben, wie man einen Uno in ein Programmiergerät verwandelt, um andere MCUs zu programmieren. Wenn man dies mehr als einmal tun will, lohnt es, ein spezielles ISP-Kabel mit einer herausgebrochenen RESET-Leitung und einem Blockkondensator für die RESET-Leitung des Programmiergeräts zu verwenden, wie von dmjlambert in seinem Instructable beschrieben.

Unabhängig davon, ob man ein spezielles ISP-Programmiergerät verwendet oder einen Uno in ein Programmiergerät umwandelt, kann man nun Fuses anderer AVR MCUs lesen und schreiben. Zu diesem Zweck muss man das Programm avrdude installieren. Wahrscheinlich ist eine Version bereits als Teil der AVR-Toolchain der Arduino IDE installiert.

Für den Mac würde ich vorschlagen, mit homebrew die neueste Version zu installieren, die in der offiziellen Codebasis verfügbar ist. Unter Linux verwenden man einen Paketmanager, um die aktuellste Version zu erhalten. Unter Windows benutzt man entweder die Version, die Teil der Arduino IDE ist, oder holt sie sich aus einer AVR-Toolchain, z.B. aus Zaks Sammlung.

Nehmen wir an, wir verwenden einen Uno, der zum ISP-Programmer umfunktioniert wurde, und unser Zielchip ist ein ATmega328P. Dann könnten wir den folgenden Befehl in einer Shell eingeben und würden darauf die angegebene Antwort erhalten (dabei ist serialport der serielle Port des ISP-Programmers):

> avrdude -c arduino -p m328p -b 19200 -P serialport -U lfuse:r:-:h -q -u 
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading lfuse memory:
avrdude: writing output file ""
0xff
avrdude done.  Thank you.

>

Kurz gesagt bedeutet dies, dass die Low-Fuse einen Wert von 0xFF hat, was bedeutet, dass kein Fuse-Bit im Low Fuse-Byte programmiert (oder gesetzt) wurde. Aber was bedeutet das? Eine Möglichkeit, diese Frage zu beantworten, besteht darin, die Bedeutung der Fuse-Einstellungen im Datenblatt nachzuschlagen, das auf der Microchip-Website verfügbar ist. Eine einfachere Möglichkeit ist die Verwendung des von Mark Hämmerling erstellten Online-Fuse-Rechners. Die elegantere Lösung wäre ein GUI-Wrapper für avrdude, in dem die verschiedenen Fuse-Bits erklärt werden.

Für macOS gibt es AVRFuse, das sehr reibungslos funktioniert. Für Windows gibt es BitBurner, das ein wenig veraltet ist. Aus diesem Grund unterstützt es weder einige der neueren AVR-Chips noch Atmel-ICE. Eine Alternative ist avrdudess, das sich auf den oben erwähnten Online-Fusebit-Rechner stützt. Die Website behauptet, dass man es auch unter Ubuntu und macOS mit Mono laufen lassen kann. Auf dem Mac unter Big Sur scheint dies allerdings nicht zu funktionieren. Außerdem war ich nicht in der Lage, es unter Ubuntu 18.04 zum Laufen zu bringen. Es scheint also keine avrdude-GUI für Linux zu geben, d.h. man muss den oben erwähnten Online-Fusebit-Rechner verwenden und dann die richtigen avrdude-Argumente manuell setzen.

Natürlich könnte man auch MPLAB X herunterladen, das für alle drei Plattformen funktioniert. Diese IDE enthält einen Fuse-Editor. Auch Microchip Studio 7, das nur für Windows verfügbar ist, enthält einen solchen Editor.

Wiederbelebung von gebrickten MCUs

Was macht man nun, wenn man es geschafft hat, das falsche Fuse-Bit zu setzen und die MCU scheinbar „tot“ ist? Die Lösung ist die Hochspannungsprogrammierung, wobei „hoch“ hier 12 Volt bedeutet, die an den RESET-Pin angelegt werden. Es gibt einige Hochspannungsprogrammiergeräte, wie z.B. den AVR Dragon (nicht mehr lieferbar), den AVR STK500 mit RS232-Schnittstelle (> €100) oder den AVR STK600 (> €200). Solch ein Gerät zu kaufen, nur um einen Chip wiederzubeleben, der weniger als 5 € kostet, scheint etwas übertrieben zu sein. Man kann sich jedoch ein eigenes HV-Programmiergerät auf einem Steckbrett mit relativ geringem Aufwand bauen. Man braucht lediglich:

  • einen Arduino Uno (oder etwas Gleichwertiges),
  • ein Steckbrett,
  • eine externe geregelte 12-Volt-Quelle,
  • ein paar Widerstände,
  • einen PNP- und einen NPN-Transistor,
  • und einige Drahtbrücken.

Wenn man einen ATmega328 wiederbeleben will, könnte das wie in der folgenden Abbildung aussehen.

Hochspannungsprogrammiergerät auf einem Steckbrett aufgebaut

Wegen der vielen Jumper-Drähte sieht es vielleicht etwas chaotisch aus. Auf meiner RescueAVR-GitHub-Seite ist jedoch alles detailliert erklärt. Dort findet man auch den Arduino-Sketch, den man benötigt, um den toten Chip wieder zum Leben zu erwecken. Anstatt ein Breadboard zu verwenden, kann man auch eines der vielen DIY-Boards für die Hochspannungsprogrammierung kaufen. Auf eBay oder Tindie wird man bei einer Suche nach HVPP und HVSP schnell fündig.