Wie gehen JTAG, Eclipse und Nexus mit Multicore-Hardware um?

10. März 2009, 14:27 Uhr | Todd Brian, Lyle Pittroff und Aaron Spear
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 2

Multicore-geeignete Debugger

Das Debuggen von Embedded-Zielsystemen hat sich in den letzten 20 Jahren deutlich weiterentwickelt. Embedded-Designer sind nicht mehr länger auf „printf debugging“ angewiesen, das nun wirklich unbequem ist. Heute verwenden Entwickler robuste Debugging-Software-Pakete, die hardwareunterstützte Schnittellen (z.B. JTAG) zum Download von Applikationen und zur Steuerung der Zielsysteme nutzen. Gute kommerzielle Pakete gestatten es dem Entwickler, nicht nur den Prozessor zu starten und anzuhalten, sondern bieten auch intuitive Möglichkeiten, Register, Speicher und Stacks zu überwachen. Einer der schwierigsten Teile bei der Embedded-Entwicklung ist es, das Verhalten des Systems zu verstehen. Debugger sind die Werkzeuge, die dem Entwickler einen Einblick in den inneren Ablauf einer Applikation geben.

passend zum Thema

Das Debugging eines Multicore-Zielsystems durchkreuzt diese Pläne jedoch. Wie steuert man einen Kern mit einem Debugger, der mit allen Kernen verbunden ist (oder mit einem separaten Debugger für jeden Kern)? Wie werden Daten für mehrere Kerne optimal organisiert, damit es für den Entwickler sinnvoll ist (und ändert sich das zwischen einem Zweikernsystem und einem System mit 300 Kernen)? Wie viele Kerne kann ein Ingenieur zur gleichen Zeit überwachen und dennoch verstehen, was in jedem einzelnen vor sich geht? Dies sind Fragen, die die Industrie beantworten muss, bevor Multicore-Designs ihre volle Leistungsfähigkeit ausschöpfen können.

JTAG –Urvater moderner Debug-Interfaces

Einer der größten Unterschiede zwischen dem Debugging von Desktopund Embedded-Systemen ist, dass sich die Embedded-Ziele außerhalb des Desktop-Systems befinden und auf irgend eine Art und Weise mit einer Debug-Konsole bzw. der Entwicklungsumgebung (Integrated Development Environment, IDE) verbunden werden müssen. Die Bandbreite dieser „Verbindungen“ reicht von zweiadrigen Kabeln bis hin zu komplexen und zweifellos wesentlich teureren Joint-Test-Action-Group-Adaptern (JTAG) mit einer großen Speicherkapazität. Manche verfügen sogar über Festplatten zur Zwischenpufferung der Daten. Der Host kommuniziert über diese Verbindungen mit dem Zielsystem. Bei einfachen zweiadrigen Kabeln ist die Interaktion zwischen der IDE auf dem Entwicklungscomputer und dem Zielsystem jedoch eingeschränkt.

JTAG-Verbindungen ermöglichen „Onchip-Debugging“. Sie gestatten der IDE die Interaktion mit dem Zielsystem und bieten Dienste wie ferngesteuertes Starten, Stoppen oder Unterbrechen der Programmausführung (Setzen eines Haltepunkts). Zudem erlauben sie dem Anwender das Betrachten der Speicher- und Registerinhalte sowie der Ein-/Ausgabe- und Peripheriegeräte. Die IDE verwendet eine Sequenz dieser Funktionen, so dass der Entwickler Haltepunkte setzen oder den Code in Einzelschritten ausführen kann.

Doch warum ist JTAG etwas Besonderes? Früher wurden Leiterplatten mit einem so genannten „Nagelbett“ getestet. Im Grunde verfügten die Baugruppen über Testpunkte (Löt-Pads), die an strategischen Punkten auf der Leiterplattenunterseite platziert waren. Nach dem Bestücken mit Chips war einer der letzten Fertigungsschritte der Test der Platine auf dem Nagelbett. Dieses hatte mehrere Stifte, die den Kontakt mit den Testpunkten herstellten. Als sich die Technologie weiterentwickelte und sich immer mehr Funktionen von der Baugruppe in Mikroprozessoren und ASICs verlagerten, wurde die Verbindung zu den Testpunkten zum Problem. 1985 schlossen sich mehrere Unternehmen zusammen, um JTAG zu entwickeln. Die Resultate von JTAG wurden 1990 vom IEEE akzeptiert und als Standard IEEE 1149.1 bzw. „Standard Test Access Port and Boundary Scan Architecture“ etabliert. Die Bezeichnung JTAG wurde gewählt, da „STAPBSA“ schwer auszusprechen ist. Die Boundary-Scan-Methode ermöglicht In-Circuit-Tests und machte das Nagelbett überflüssig.

Die Verwendung von JTAG-Scanning-Schnittstellen, die zunächst für Boundary-Scan-Tests von komplexen Geräten und Baugruppen entwickelt wurden, wurde auch zur Standardmethode für den Zugriff und das Debugging von Prozessorkernen. Dies liegt sowohl an der kleinen Anzahl benötigter Pins als auch daran, dass sie bereits weithin für ihren ursprünglichen Zweck adaptiert wurden. Um JTAG zum Debuggen von Prozessoren verwenden zu können, müssen dem Design des CPU-Kerns eine Debug-Support-Unit oder „debug logic“ sowie ein zusätzlicher JTAG-Scan-Pfad für den Zugriff auf die Logik hinzugefügt werden. Bild 1 zeigt einen JTAG-TAP (Test Access Port) mit seinen vielfältigen JTAG-Scan-Pfaden.

Separate Scan-Registerpfade stehen für Boundry-Scan zur Verfügung, lesen den Geräte-ID-Code, initiieren eingebaute Selbsttestfunktionen und erhalten deren Ergebnisse. Außerdem greifen sie auf die Debug-Support-Unit zu. Das TAP-Instruction-Register (TAPIR) wird zur Auswahl des gewünschten Pfades verwendet. Da das TAP während des normalen Betriebs im Bypass-Stadium bleibt, sind die anderen Funktionen deaktiviert.

9040901_tm_03.jpg
Bild 1. Ein einzelner JTAG-Test-Access-Port (TAP) mit seinen vielfältigen JTAG-Scan-Pfaden. Über eine einzige Schnittstelle kann auf alle gezeigten internen Einheiten des Prozessors zugegriffen werden.

Die kostengünstigste Konfiguration (mit der niedrigsten Anzahl von Pins) für Multicore-Geräte erreicht man, wenn man JTAG-TAPs innerhalb eines jeden Kerns nach dem Daisy-Chain-Prinzip aneinanderreiht (Bild 2). Auf diese Weise werden die Befehlsregister für jeden TAP in einem langen Befehlsregister aneinandergehängt. So kann ein spezieller Kern an einer bekannten Position in der Scan-Kette gesetzt werden, um die Register der Debug-Support-Unit zu wählen, und alle anderen Register können in den Bypass-Modus gesetzt werden. Dies gestattet es, einen Kern individuell mit einem Debugger-Control-Paket zu adressieren.

Wird dieses Konzept erweitert, können mehrere Debugger jeweils einzelnen Kernen zugewiesen werden und diesen Kernen Debug-Service-Control-Pakete senden, ohne andere Kerne (Shared-Memory-Aspekte werden für den Moment ignoriert) zu beinträchtigen. Dies ist möglich, da Ethernet-Debug-Service-Pakete in der Reihenfolge ihres Eintreffens aneinandergereiht und ausgeführt werden.

Individuelle Befehle, die an einen CPU-Kern über JTAG ausgegeben werden, erfordern Hunderte von JTAG-Operationen. Obwohl es zumindest für den menschlichen Betrachter den Anschein hat, dass diese sehr schnell ausgeführt werden (die JTAG-Scan-Kette führt serielle Scans üblicherweise mit 10 bis 40 MHz durch), ist dies im Vergleich zu einer CPU, die mit ca. 400 MHz bis 1,2 GHz läuft, eigentlich ein sehr langsamer Prozess.

9040902_tm_03.jpg
Bild 2. Mehrere Kerne auf einer JTAG-Scan-Chain. JTAG ist kostengünstig, weil man durch das Daisy-Chain-Prinzip mehrere Kerne durch wenige Leitungen ansprechen kann.

  1. Wie gehen JTAG, Eclipse und Nexus mit Multicore-Hardware um?
  2. Wie gehen JTAG, Eclipse und Nexus mit Multicore-Hardware um?
  3. Multicore-geeignete Debugger
  4. Wie gehen JTAG, Eclipse und Nexus mit Multicore-Hardware um?
  5. Wie gehen JTAG, Eclipse und Nexus mit Multicore-Hardware um?

Jetzt kostenfreie Newsletter bestellen!