Philosys bietet individuelle Dienstleistungen in den Bereichen Unix/Linux System- und Netzwerksoftware, technische und Echtzeit-Applikationen sowie Embedded Linux.

11. Februar 2009 — Emil Näpflein
Debugging eines seriellen Treibers für Embedded Linux unter Zuhilfenahme eines Logikanalyzers.
Nachdem die Funktionalität des Treibers für den Duart TL16C752B von Linux 2.4 auf 2.6 portiert war, stand der Test und das Debugging an. Da die Hardware zwei RS485-Schnittstellen zur Verfügung stellt, erfolgt dies erstmal dadurch, dass die beiden Schnittstellen über ein gekreuztes Kabel verbunden werden. Ein einfaches Testprogramm sendet einen Block an Daten über die eine Schnittstelle und ein zweites liest die Daten und sendet sie zurück. Wie im Ping-Pong soll dies alles ablaufen — die Betonung liegt auf dem soll. Leider sieht es so aus, als wenn die Daten auf der Gegenseite nicht ankommen und alles hängt.
Zuerst werden die Testprogramme nochmal überprüft, sie funktionieren aber auf zwei anderen RS485-Schnittstellen, die durch einen anderen Treiber bedient werden, problemlos. Auch die Verkabelung wird nochmal überprüft — ist aber ok. Der nächste Test erfolgt zwischen einer Schnittstelle, die definitiv funktioniert und einer, die nicht funktioniert. Doch weder das Senden, noch das Empfangen von Daten gelingt.
Da kein BDI zur Verfügung steht, bleibt nichts anderes übrig, als Traces in den Treiber einzubauen. Schnell stellt sich heraus, dass beim Anstoßen des Sendens gar kein Transmit-Interrupt kommt - die Daten werden also gar nicht erst versendet. Weitere Traces werden eingebaut, um die Programmierung des Chips zu beobachten. Hier stellt sich heraus, dass immer das IRQ Enable im Modem Control Register (MCR) zurück gesetzt wird. Ganz grundsätzlich funktioniert der Transmit-Interrupt, da bei der Initialisierung auch der richtige IRQ gefunden wird. Ein Versuch, den Interrupt im MCR direkt vor der Sendefunktion einzuschalten, scheitert. Es stellt sich heraus, dass weitere Registerzugriffe auf andere Register das IRQ Enable wieder zurücksetzen. Der Knackpunkt scheint die Reihenfolge zu sein.
Dadurch, dass die Funktionalität für den TL16C752B in den 8250-Treiber integriert wurde, hat sich irgendwas geändert. Ein Review des alten Treibers ergab dann, dass das IRQ Enable nur einmal während der Initialisierung gesetzt wird und sonst automatisch immer bei jedem Schreiben mit enthalten ist. Der 8250-Treiber wurde entsprechend geändert und — BINGO — die Zeichen huschen hin und her. Schon vorher hatte ich einen Logikanalyzer angeschlossen, um zu sehen ob überhaupt Zeichen zu sehen sind. Der Logikanalyzer bietet hier normalerweise durch Nachbereitung der aufgezeichneten Daten eine lesbare Darstellung des seriellen Datenstromes. Doch bisher war absolute Stille.
Damit schien das Problem erledigt. Doch ein weiterer Test der Interoperabilität mit anderen RS485-Schnittstellen zeigte, dass doch noch irgendwas nicht stimmt. Denn der Test blieb hängen. Die Vermutung ging in Richtung falscher Baudrate. Deshalb wurde mit dem Logikanalyzer die Übertragungszeit eines Zeichens vermessen. Hoppla — die Datenrate war 16-mal schneller als sie eigentlich sein sollte. Es ist also noch was mit der Programmierung der Baudrate falsch. Nach dem Review des 8250-Treibers stellte sich heraus, dass bei der Programmierung der Teiler durch 16 geteilt wird, gleichzeitig wurde aber die Clockrate des Duart wie im alten Treiber schon in der Konfigurationstabelle durch 16 geteilt. Das war ein Mal zu viel. Nach der Korrektur funktionierte auch der der Test mit anderen Schnittstellen.
Fazit:
Die Ursache für Probleme liegt oft an ganz kleinen Dingen. Gerade bei der Portierung von Funktionalität von einem Treiber in einen anderen gibt es immer wieder Randbedingungen, die leicht übersehen werden. Und gerade bei Treiber-Problemen können externe Hilfsmittel wie ein Logikanalyzer ganz hilfreich sein. Sie können zeigen, was die Hardware wirklich tut und so die Diagnosezeit erheblich verkürzen.