Hallo zusammen, ich möchte zu Lehrzwecken einen Treiber unter Linux schreiben. Ich habe dazu auch ein gutes Tutorial gefunden. Allerdings mehr oder minder für die Grundfunktionen eines Treibers. Programmiert wird das Treibermodul in C. Die Idee: Meine Projekt (die meist mit atMega laufen) direkt per Treiber anzusprechen. Zum Beispiel über die write Funktion einen Befehl an dem µC senden. Dabei muss der Befehl entweder durch einen USBtoSerial-Converter oder per Ethernet über IP/UDP an einen Port gesendet werden. So will ich mir die eigene Eingabe über einen Terminal sparen und das Ansprechen mit einem anderen Programm vereinfachen. Dazu erstmal eine Verständnisfrage: Ein normaler Geräte Treiber spricht Hardware direkt an, wie zum Beispiel die RS232 (Serielle Schnittstelle). Die Treiber sind unter Linux vorhanden. Dies muss bzw. will ich nicht programmieren. (Für was auch? :) ) Aber ist es überhaupt möglich per Gerätetreiber ein Gerät hinter einem anderen Gerät anzusprechen? Was ich meine: Kann ein Treiber unter Linux über einen anderen Treiber (z.B.: USB (USBtoSerial) ein Gerät(atMega) ansprechen? Ist es überhaupt möglich ein Gerät zu "emulieren", dass über Ethernet (ein Netzwerktreiber) gesteuert wird? Meine Frage, die sich auftun: Wenn es möglich ist, zum Beispiel per USBtoSerial den µC dahin anzusprechen, kann ich dann einfach die Serielle Schnittstelle öffnen? Also Öffnen wie in einem Programm auch? Ich denke, dass dies nicht so einfach möglich ist, da wir uns im Kernelmodus befinden. Gibt es dazu ein Lösung? Vielleicht hat jemand damit schon Erfahrungen gemacht und könnte mir ein paar Hilfestellungen oder Tipps in der Programmierung geben.
Treiber brauchst Du für HW Zugriff den das OS normalerweise unterbinden würde weil ein Programm im Userspace die Rechte nicht hat. Wozu brauchst Du für das Vorhaben einen Treiber?
cyberhong schrieb: > Wenn es möglich ist, zum Beispiel per USBtoSerial den µC dahin > anzusprechen, kann ich dann einfach die Serielle Schnittstelle > öffnen? Also Öffnen wie in einem Programm auch? > Ich denke, dass dies nicht so einfach möglich ist, > da wir uns im Kernelmodus befinden. Internet per ppp ist vielleicht ein Beispiel wo das gemacht wird. An einem klassischen COM-Port hängt ein serielles Modem. Dann muss es etwas geben, was ppp versteht und am einen Ende mit dem Modem redet. Am anderen Ende sieht dieses Etwas wie ein Netzwerk-Interface aus. Dieses Etwas läuft doch bestimmt im Kernelmodus, also darf man es Treiber nennen(?)
cyberhong schrieb: > Die Idee: Meine Projekt (die meist mit atMega laufen) direkt per Treiber > anzusprechen. Zum Beispiel über die write Funktion einen Befehl an dem > µC senden. Dabei muss der Befehl entweder durch einen > USBtoSerial-Converter oder per Ethernet über IP/UDP an einen Port > gesendet werden. Für beides brauchst du keinerlei eigene Treiber zu schreiben, die hat Linux bereits. Was du wahrscheinlich eigentlich willst, ist eine Anwendung zu schreiben, die die vorhandenen Treiber benutzt. Also: Lerne programmieren!
Anwendungen für meine Projekte habe ich breits geschrieben. Mich interessiert die Treiberprogrammierung. Mit einem Treiber besteht die Möglichkeit unter Linux einfach durch open oder write Befehle ausführen zu lassen oder vom µC zu lesen ohne das Serielle Interface zu öffnen, Baud usw. eingeben zu müssen. Das könnte der Treiber übernehmen. Damit könnte der Anwender oder ein anderes Programm einfach die Dateioperationen benutzen und muss im Hintergrund nicht wissen, wie die Hardware tatsächlich angesprochen wird.
Und wie wird das Serialport configuriert ? Einfach COM3 ? Uups - geht nicht ?
Ween ich es richtig verstehe willst Du einen Linux-Kernel-Treiber der eine serielle Schnittstelle benutzt (nicht bereitstellt). Also: User-Space <-> Treiber <-> serielle Schnittstelle (UART, USB, ...) <-> Device Das Stichwort bei Linux heisst "serdev". Da gibt es im Kernel ein paar Beispiele (v.a. für GPS- oder Bluetooth-Devices): http://events17.linuxfoundation.org/sites/events/files/slides/serdev-elce-2017-2.pdf https://elixir.bootlin.com/linux/latest/source/include/linux/serdev.h https://elixir.bootlin.com/linux/latest/C/ident/serdev_device Es ist sowieso am besten einen möglichst ähnlichen Treiber zu suchen, den zu kopieren (neuer Name) und dann anzupassen als bei 0 anzufangen... Was noch zu überlegen ist, ist wie das User-Space-Interface aussieht. Ob es ein /dev werden soll, das man per ioctl() oder read/write() ansteuert. Oder ein File in /proc oder /sys. Und es stellt sich die Frage wie man dem Kernel nun sagt dass der neue Treiber ein ganz bestimmten seriellen Port verwenden soll. Auf vielen Systemen geht das per Device-Tree.
Nikolaus S. schrieb: > Ween ich es richtig verstehe willst Du einen Linux-Kernel-Treiber der > eine serielle Schnittstelle benutzt (nicht bereitstellt). > > Also: > > User-Space <-> Treiber <-> serielle Schnittstelle (UART, USB, ...) <-> > Device Genau das habe ich vor ;) Danke für deinen Beitrag
Pandur S. schrieb: > Und wie wird das Serialport configuriert ? Das könnte man beim Laden des Treibers herausfinden. Er schickt einfach eine Anfrage an alle Ports raus, der µC antwortet dann mit einer Magic Number. So mache ich das Programmen auch schon. Damit muss der Anwender nicht den Port oder Schnittstelle kennen....
Treiber für eine USB-Soundkarte sprechen auch die Karte an über USB, dass es vor dem Einstecken der Karte schon gab. Das Einstecken der Karte erzeugt ein neues USB-Device dass du mit deinem Treiber ansprechen kannst.
:
Bearbeitet durch User
cyberhong schrieb: > Das könnte man beim Laden des Treibers herausfinden. Vielleicht solltest du einen anderen Ausdruck verwenden: Du willst keinen Hardware-Treiber programmieren. Den gibt es schon im Kernel und ud wirst das nicht besser hinbekommen. Vielmehr willst du eine Programmbibliothek (Library) schreiben die diverse Applikationen einbinden und die dann je nach Einstellungen oder Aufruf die Kommunikation mit dem Hardware-Treiber herstellt.
Das hier wäre ein Beispiel für einen Hardware-Treiber im Linux-Kernel, der einen AVR anspricht: https://github.com/harbaum/I2C-Tiny-USB/blob/master/kernel/i2c-tiny-usb.c allerdings über USB, nicht seriell.
Es gibt einen off-tree kernel for das Pinephone Pro, wo ein Treiber drinn ist, um ein Modem ein und aus zu schalten. Das nimmt sich einen Seriellen Anschluss (definiert per device tree), der dann im userspace nicht mehr zur verfügung steht, setzt ein paar GPIOs und sended ein paar AT befehle beim ein / ausschalten vom Modem. https://megous.com/git/linux/tree/drivers/misc/modem-power.c?h=orange-pi-5.16#n501
Ich spreche alle möglichen Geräte (seriell oder USB) nur im Usermodus an. Dazu brauche ich in Linux keine extra Treiber. Serielle Schnittstellen (z.B. /dev/ttyS0, oder wie sie auch immer heissen) kann man einfach mit open() öffnen, mit write() beschreiben. USB-Serial Adapter werden vom Linux-Kernel meist schon auf seriell gemappt, so dass der Weg mit open() auch geht. Bei komplexeren USB-Geräten nehme ich die LibUSB. Die kann ich über eine API im Userspace ansprechen. Und bei Kernel-Treibern muss man für jede neue Kernelversion auch den Treiber neu kompilieren. Will ich nicht, zu aufwändig. Bleib im Userspace. Versuche erst einmal auf normalen Leveln eine Kommunikation hin zubekommen.
Ich habe den TO so verstanden dass er - zu Lernzwecken - einen Linux-Treiber schreiben möchte. Als Beispiel hat er die Kommunikation mit einem Atmel mittels Serieller Schnittstelle (oder USB) ins Spiel gebracht. Jetzt ist das zwar nicht direkt ein Szenario wo man einen eigenen Treiber schreiben müsste. Das geht, wie festgestellt wurde, auch alles im Userspace. Dennoch unterscheidet sich das Vorgehen beim Schreiben eines "normalen" Userspace-Programms doch sehr von der Programmierung eines Treibers welcher im Kontext des Kernels läuft. Deswegen: ja, auch wenns einfacher ginge, solange der Lerneffekt im Vordergrund steht halte ich die Idee des TOs für durchaus sinnvoll. Die Idee hat auch den Charm dass man Teile des Programms, z.B. einen etwaigen Kommando-Parser, Statemachines für die Kommunikation etc. erstmal als Userspace-Programm testen und dann in den Kernelspace portieren kann. @ TE: ignorier die Unken, finde deine Idee gut. Du hast dir ein schönes Beispiel ausgewählt.
cyberhong schrieb: > Die Idee: Meine Projekt (die meist mit atMega laufen) direkt per Treiber > anzusprechen. Deine Idee ist wirr und mir nicht verständlich.. Also: Ein Treiber ist ein Stück Programm, das eine Betriebssystem-Funktion auf eine bestimmte Peripherie der Rechenkiste leitet. Ein außen an irgend eine Schnittstelle angeschlossener µC ist jedoch keine Peripherie, sondern eben bloß ein drangestecktes Gerät. Wenn dein µC über eine der üblichen Schnittstellen an deinen PC angeschlossen ist, z.B. einen seriellen Kanal, dann können alle Programme über diesen Kanal mit dem µC kommunizieren. Dabei ist es völlig wurscht, ob ein Teil dieses Kanals über einen USB geht oder von einem reitenden Marsmännchen erledigt wird. Was du vermutlich am ehesten benötigst, ist ein Protokoll auf dem Kanal, an das sich alle Programme halten sollen. Nun, das mußt du dir selber ausdenken, aber das ist kein Teil irgend eines Kanals, der aus dem PC heraus bzw. herein führt. Insofern brauchst du keinen Treiber zu schreiben. Ich geb dir mal einige Beispiele: 1. die klassische Kommandozeile. Da wird jedes Kommando auf einer mit Zeilenschaltung (bei Windows: CR und LF) abgeschlossenen Kommandozeile mit Echo gesendet, für Ausgaben des µC zum PC hin gibt es keine Festlegungen. Beispiel:
1 | DISPLAY 100 1FF (cr)(lf) |
2. die einfache, aber noch lesbare Maschine zu Maschine Kommunikation: dort werden Kommandos, die aus Einzelbuchstaben bestehen, mit eventuell vorangestelltem rein numerischen Parameter OHNE Echo gesendet. Ausgaben sind wieder nicht festgelegt. Beispiel:
1 | 64A127D |
3. wie 1 oder 2, aber der Zeichenvorrat ist wertemäßig aufgeteilt. Beispiel: 0..0F - Kommandoverkehr 10..1F - Alternativ-Verkehr 20..5F - Kommandoverkehr 60..7F - Statusmeldungen 80..FF - Alternativ-Verkehr Hierbei können beide Geräte (PC und µC) anhand des transferierten Wertes unterscheiden, zu welchem Funktionsbereich der transferierte Wert gehört. Damit können in beiden Richtungen Informationen zu unterschiedlichen Funktionsgruppen bzw. Programmteilen geschickt werden, ohne daß sie sich gegenseitig stören. Man kann sich so oder anders verschiedenste Protokolle ausdenken, mit denen man über einen (ziemlich beliebigen) Kanal die Kommunikation zwischen Programmen auf dem PC und der Firmware in einem µC organisieren kann. Ich vermute mal, daß dir im Grunde irgend so etwas als Ziel der ganzen Übung erscheint. W.S.
W.S. schrieb: > Ich vermute mal, daß dir im Grunde irgend so etwas als Ziel der ganzen > Übung erscheint. Nö, er möchte als Übung einen Linuxtreiber schreiben. Der könnte auch über USB mit AVR sprechen. Eben z.B. ein bestimmtes Protokoll.
cyberhong schrieb: > ich möchte zu Lehrzwecken zu Lernzwecken empfehle ichm Sie lernen zuerst korrekt zu schreiben, Gute Besserung!
Trollarzt schrieb: > zu Lernzwecken empfehle ichm Sie lernen zuerst korrekt zu schreiben, > > Gute Besserung! LOL! Gleichfalls.
900ss D. schrieb: > Nö, er möchte als Übung einen Linuxtreiber schreiben. Der könnte auch > über USB mit AVR sprechen. Eben z.B. ein bestimmtes Protokoll. Wenn einer ohne Not einen Gerätetreiber für sein OS zu schreiben beabsichtigt, dann nur zu! Einfach machen. Das war ein Zitat. Aber so ein Treiber interessiert sich normalerweise nicht für die Bedeutung der Daten, die er von A nach B zu schaufeln hat. Auch nicht für irgendwelche Protokolle. Auch nicht für die Bauart eines an den PC gestöpselten µC. Allenfalls interessiert sich irgend eine andere Verwaltungsstelle im OS für vid&pid, falls das Ganze sich auf den USB beziehen sollte. W.S.
W.S. schrieb: > Aber so ein Treiber interessiert sich normalerweise nicht für die > Bedeutung der Daten, Sicher könnte er aber. Er könnte doch ein spezifisches Protokoll sprechen?
Ich sehe da eher, dass jemand ein Block-Device bauen will, auf das er mit Dateioperationen zugreifen will. Für Seriell ist das aber nicht notwendig, da der Kernel hier bereits ein Blockdevice anbietet. Angenommen das Gerät ist über RS232 angebunden und versteht, aus Platzgründen, nur Einzeichenkommandos oder nur eine binäre Übertragung. In diesem Fall könnte man schon ein Block-Device verwenden, um die Kommandos in, für Menschen lesbare Form zu bringen. Schickt man eine CSV an das Device, würden die Daten beispielsweise in die benötigte Form umgewandelt oder auch komprimiert. So könnte man beispielsweise einen µP direkt mittels "cat daten.bin > /dev/winzigweich" programmieren.
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.