Im Rahmen der Entwicklung der I2C-Platine, die ja eigentlich zum Neustarten hängengebliebener Rechner dienen soll, tauchte die Frage auf, was zu machen ist, wenn sich der Raspberry aufgehangen haben sollte. Erfahrungsgemäß hängt sich jedes System irgendwann mal auf, in aller Regel handelt es sich dabei nicht um schwerwiegende Störungen, sondern eher um zufällige Ereignisse.
Daher wurde hier kurz ein Watchdog entwickelt, der dafür sorgen soll, dass sich der Raspberry selber neu startet, wenn das System mal komplett hängengeblieben ist.
Bei der Revision 1 der B-Serie haben wir dabei noch das Problem, dass kein offizieller Reset-Anschluss existiert. Bei Revision 2 ist das geändert. Aus diesem Grund muss der Watchdog sowohl in der Lage sein, den Raspberry per Aus-Ein-Schalten neu zu starten als auch per normalem Reset.
Basis der entstandenen einfachen Schaltung ist der Zeitgeber-Schaltkreis NE555. Ob man hier den alten einsetzt oder die CMOS-Variante ist relativ egal.
Der NE555 steuert über einen pnp-Transistor das Relais, mit welchem entweder eine Resetleitung bedient wird oder aber die Stromzufuhr zum Raspberry unterbrochen wird.
Da der Ausgang des NE555 nach einem Neustart bzw. nach dem Zurücksetzen auf "L"-Pegel ist, zieht das Relais nach dem Einschalten kurz an, was aber nicht stört, da der Raspberry ohnehin noch nicht wirklich läuft. Im Gegenteil: Bei der endgültigen Anwendung im IP-Reset-Controller war das von Vorteil, da der Raspi dann erst einige Sekunden nach der Festplatte eingeschalten wird, was dieser (bzw. dem USB-Plattenadapter) den Vorlauf verschafft, um dann wirklich bereit zu sein, wenn der Raspi bootet.
Der "H"-Pegel, der sich am Kollektor von T2 einstellt, sorgt dafür, dass zeitverzögert über das RC-Glied R3/C4 der Transistor T3 durchsteuert. Damit wird der Triggereingang von IC1 auf "L" gelegt, mit der H-L-Flanke beginnt der Zeitgeber zu arbeiten und C3 wird über R4 aufgeladen.
Normalerweise sollte beim NE555 eine Schaltzeit von ca. 1.1*C3*R4 entstehen. Das war bei mir nicht der Fall, hier liegt der Faktor bei ca. 1.5. Aus der gewählten Kombination 100KOhm für R4 und 2200µF für C3 entsteht hier eine Schaltzeit von ca. 330 Sekunden, also 5,5 Minuten. Bei einer Testkombination von 10KOhm/1000µF waren es 15 Sekunden. Möglicherweise liegt das mit an den höheren Eingangsströmen des alten bipolaren NE555, bei der CMOS-Variante sollte sich der Faktor 1.1 einstellen
Das RC-Glied R3/C4 ist so gewählt worden, dass eine "schöne lange" Aus- bzw. Reset-Zeit entsteht. Dabei stellt sich nach ca. 5 Sekunden die erforderliche Basisspannung von ca. 0.7V an T3 ein. Das Relais zieht also für ca. 5 Sekunden an, dann beginnt der Timer wieder zu arbeiten und es fällt für die erwähnten 330 Sekunden wieder ab.
Der Raspberry hat jetzt die Aufgabe, rechtzeitig vor Ablauf der 330 Sekunden, also mindestens alle 5 Minuten, einen "H"-Impuls an K1 zu schicken, damit T1 einen "L"-Impuls an den Kollektor legen und damit den zeitbestimmenden C3 wieder entladen kann. Bei jedem Impuls, den der Raspberry schickt, wird also der Timer neu gestartet, weil der Ladekondensator wieder neu geladen werden muss.
"Vergisst" der Raspberry das Schicken der Impulse, wird nach 330 Sekunden wahlweise der Strom abgedreht oder die Resetleitung betätigt. Dementsprechend muss nach einem Neustart des Raspberry auch spätestens die Software arbeiten, die die regelmäßigen Pulse generiert, und auch gleich den ersten Puls abgeben. Das bedeutet, dass die Software noch vor einem möglichen Plattencheck geladen sein muss.
Schaltplan und Board-Layout im "Target 3001!"-Format
Schaltplan als PDF
Software zur Ansteuerung
Die simpelste Variante ist z.B. ein kleines Python-Script, welches über eine init.d-Startdatei beim Booten aktiviert wird. Hier ein Beispiel, welches den Pin 26 des GPIO-Connectors benutzt (das wäre dann das Signal GPIO 7):
#! /usr/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(26, GPIO.OUT)
GPIO.output(26, False)
while (True):
GPIO.output(26, True)
time.sleep(1)
GPIO.output(26, False)
time.sleep(60)
Damit wird das Pin 26 einfach als Output definiert, gleich auf Low gelegt und dann im Abstand von 60 Sekunden immer für eine Sekunde ein High erzeugt. Dieses steuert dann Transistor T1 durch und entlädt den Zeitgeber-Elko.
Durch die Benutzung von Python und die damit verbundene Umgebung ist das Script relativ speicherhungrig, etwa 4MB gehen dabei an aktivem Speicher drauf. Ein kleines C-Programm ist da nicht ganz so hungrig.
Anmerkung zum 2012-10-30: Dieses Projekt wird nicht mehr separat weiterentwickelt, sondern ist Teil des neuen Projekts mit der eigentlichen Zielstellung (dedizierter IP-Resetswitch auf Basis des Raspberry Pi). Dorthin kommt man über diesen Link.