Trotzdem ist es nicht ganz einfach
Zuerst probiere ich, einen Device Tree zu bauen, um den Kernel für die Hardware zu konfigurieren. Allerdings funktioniert das nicht. Das Device-Tree-Konzept war noch im Entstehen begriffen, als die Unterstützung für den SoC im Kernel hinzugefügt wurde. Nachdem ich einen Tag damit verschwendet habe, finde ich heraus, dass die Device-Tree-Unterstützung für den SoC nie fertiggestellt wurde, die Infrastruktur für Taktraten und Interrupts ist im Mainline-Kernel sogar komplett kaputt.
Ich beschließe, die Unterstützung im Linux-Kernel für den SoC wie in früheren Zeiten zu implementieren: per Maschinendatei. Also packe ich die Hardware-Konfiguration in die mach-smdk2416-Datei. Sie wird zur Konfiguration der Samsung-Referenz-Plattform des S3C2416-SoC verwendet, und damit geht es.
Allerdings habe ich auch noch einige Probleme mit OpenOCD. Wenn der Linux-Kernel bootet, müssen die MMU und die Caches des SoC deaktiviert werden. Das soll mit dem "mcr"-Kommando in OpenOCD möglich sein, bei mir funktioniert es aber nicht. Wenn ich OpenOCD gestartet habe, die Verbindung hergestellt ist und ich "halt" eingeben habe, hat der Bootloader im Oszilloskop längst die MMC und die Caches aktiviert.
Wenn es mir aber gelingt, den Bootloader schnell genug zu stoppen, nachdem ich das Oszilloskop angeschaltet habe, dann hat der erste Teil des Bootloaders den SDRAM-Speicherkontroller bereits konfiguriert, aber noch nicht die MMU. Ich probiere, das Oszilloskop mit der einen Hand anzuschalten und mit der anderen Hand einen Kommandozeilenaufruf auszulösen:
/opt/openocd/bin/openocd -f openocd.cfg -c init -c halt
Stimmt mein Timing, dann füllt der Bootloader den SDRAM nur mit Null auf und ich kann danach meinen eigenen Code ausführen.
Linux-Start
Mit Buildroot erzeuge ich ein gepacktes Linux-Image mit einer RAM-Disk, die Busybox enthält. So hätte ich eine Shell und eine Kernel-Kommandozeile auf dem Oszilloskop zur Verfügung. Das eigenständige Paket in einer Datei im zImage-Format kann ich per JTAG übertragen und benötige lediglich eine CPU und SDRAM zur Ausführung. Ich weise Linux an, auf dem ersten seriellen Anschluss, UART0, Debug-Meldungen auszugeben. Außerdem ergänze ich den Startup-Code im Kernel um einige Anweisungen, damit einige Register korrekt gesetzt werden.
Um den Kernel zu booten, verbinde ich mich wieder mit OpenOCD. Um sicherzugehen, überschreibe ich die Interrupt-Register, um jegliche Interrupts zu deaktivieren. Dann lade ich das zImage in den RAM und führe es aus:
mww 0x4a000008 0xffffffff mww 0x4a000048 0xffffffff mww 0x4a00001c 0xffffffff load_image zImage 0x31000000 bin resume 0x31000000
Mich überkommt ein Glücksgefühl, als der Linux-Kernel tatsächlich bootet:
Uncompressing Linux... done, booting the kernel. Booting Linux on physical CPU 0x0 Linux version 3.12.0-rc7+ (wingel@zoo) (gcc version 4.7.3 \ (Buildroot 2013.11-00004-g020dda7) ) #8 Mon Apr 26 21:14:24 CEST 2016 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: SMDK2416 Memory policy: ECC disabled, Data cache writeback CPU S3C2416/S3C2450 (id 0x32450003)
Allerdings komme ich nicht weit. Der Ausschnitt stammt noch von meinen ersten Versuchen mit dem Device Tree, und da die Timer-Interrupts nicht funktionierten, kam der Start nie über "Calibrating delay loop..." hinaus. Doch am nächsten Tag, mit dem Kernel ohne Device Tree, bootet das System bis zur Shell auf der seriellen Konsole.
Gerätetreiber
Danach aktiviere ich einen Gerätetreiber nach dem anderen. Da ich die notwendigen Konfigurationsdaten für das LCD schon habe, fange ich damit an. Ich muss wirklich nur die Werte in die mach-smdk241-Datei eintragen.
Der USB-Host-Anschluss benötigt keine weitere Konfiguration, er funktioniert einfach. Ich kann eine USB-Maus anstecken. Beim Ein- oder Ausstecken einer USB-Festplatte dagegen hängt der Kernel. Allerdings denke ich, dass dort ein elektrisches Problem vorliegt. Ich merke, dass ich nicht mal die Festplatte einstecken muss, schon die Berührung der Abschirmung des USB-Steckers mit der Buchse stoppt den Kernel. Mich interessiert wirklich, was da fehlschlägt, doch ich mache erst einmal weiter.
Der USB-Client-Anschluss ist etwas komplizierter. Linux nimmt an, dass der Takt von einem der Taktgeber der CPU auch den USB-Takt vorgibt und mit 48 MHz läuft. Das ist im Treiber hardcodiert. Der SoC verhält sich aber anders und die Konfiguration ist laut Datenblatt eigentlich inkorrekt. Aber schließlich gelingt es mir, den Treiber umzuschreiben - und dann funktioniert es.
Auch der Flash-Speicher funktioniert. Aufwendig ist nur, die richtige Syntax für das mtdpart-Argument für den Linux-Kernel-Kommandozeilenaufruf herauszufinden. Dann kann ich das Werkzeug nanddump benutzen, um den Inhalt des Flash-Speichers auszulesen. Dessen Ausgabe entspricht der Ausgabe über OpenOCD.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
- ohne Werbung
- mit ausgeschaltetem Javascript
- mit RSS-Volltext-Feed
Register auslesen | Wie es weitergeht |
+1 Mehr davon und ich abonniere auch. Und wie laoladabamba sagt, die Weltraumartikel...
Aber ehrlich. Wenn's nur News über neue Grafikkarten gibt heulen die selben Leute über...
ich seh das ja auch immer mit einem zwinkernden Auge. Entwickler sollen entwickeln und...
Die Chancen dass es ein Linux ist sind relativ gross. Würde es mich interessieren hätte...
Hier kann man mal sehen, was Fachkraft wirklich bedeutet. *Davon* haben wir zu wenige.