Hallo, ich fange an mich mit dem Programmieren eines Device Treibers für Linux zu beschäftigen. Als erstes Projekt zum Üben soll das Modul auf die SPI Hardware eines Raspberry Pi (erste Version, Modell B) ansprechen. Bytes ausgeben und einlesen geht schon mal. Was nicht geht ist ein Interrupt am Linux Kernel (4.1.13) anmelden und von der SPI Hardware auslösen lassen. Ich hab den Quelltext des Moduls mal auf das runter gebrochen was minimal nötig ist damit der Interrupt ausgelöst werden sollte. Bitte nicht vom Umfang des Codes abschrecken lassen, die wichtigsten Stationen: Z.267: wird aufgerufen wenn der Treiber eingehängt wird Init für die SPI-Hardware, hier wird auch der Interrupt beim Kernel angemeldet Z.344: wird beim Start eines Schreibzugriffs auf den Treiber aufgerufen, Setzt die Clock der SPI Hardware, aktiviert auch die Interrupts -> an sich müsste dann gleich ein Interrupt ausgelöst werden Z.251: "driver_write" Hier landen die Daten die in den Treiber geschoben werden. Die Daten werden aber ignoriert, es wird immer die gleiche Funktion aufgerufen die zwei Bytes in den SPI-FIFO schiebt. Diese beiden Bytes werden von der SPI Hardware gesendet, diese kann ich auf der Gegenstelle empfangen. Z.377: Wird aufgerufen wenn der Schreibzugriff zu Ende ist Z.414: wird beim Entladen des Treiber aufgerufen Z.454: Das ist die ISR (interrupt service routine) die offensichtlich nie aufgerufen wird (keine Daten am SPI-Ausgang und das Status-Wort wird auch nicht beschrieben) Kann man an dem Beispiel sehen was schief läuft? Melde ich den Interrupt nicht richtig am Kernel an? Löst die SPI Hardware nie einen Interrupt aus weil ich was nicht initialisiert habe? Leider gibt das Netz nicht viel her zum Thema SPI-Interrupt beim Raspberry Pi. Und der "offizielle" Treiber ist sowas von abstrakt programmiert (http://lxr.free-electrons.com/source/drivers/spi/spi-bcm2835.c) dass ich nicht erkennen kann was da genau wie initialisiert wird. Ich persönlich programmiere lieber etwas konkreter, selbst wenn es am Ende nicht so portabel ist.
Ist denn überhaupt der passende IRQ in den SPI Registern UND beim Interrupt Pendingregister freigeschalten? (Kapitel 7 im DB) Weiterhin kann es sein, dass im Linuxkernel die IRQ Nummer anders ist als im Datenblatt, hab ich beim ZYNQ schonmal so erlebt, da warn Offset von 32 drauf.
Vielen Dank für den Hinweis, das war der entscheidende Punkt: Die IRQ Nummer im Kernel stimmt nicht mit der Hardware-IRQ-Nummer überein. Für den Kernel liegt der SPI-Interrupt auf der Nummer 80: https://nigelborrington.ie/2016/04/27/device-irqs-interrupt-requests-a-definition/ Es ist wohl unsauber das fest im Sourcecode zu codieren weil sich das mit einer neuen Kernelversion ändern könnte. Aber es funktioniert jetzt und für mich ist das erst mal gut genug um weiter zu machen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.