Forum: PC-Programmierung Linux Gerätetreiber für atMegas


von cyberhong (Gast)


Lesenswert?

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.

von Max M. (Gast)


Lesenswert?

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?

von Bauform B. (bauformb)


Lesenswert?

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(?)

von c-hater (Gast)


Lesenswert?

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!

von cyberhong (Gast)


Lesenswert?

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.

von Pandur S. (jetztnicht)


Lesenswert?

Und wie wird das Serialport configuriert ? Einfach COM3 ? Uups - geht 
nicht ?

von Nikolaus S. (Firma: Golden Delicious Computers) (hns)


Lesenswert?

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.

von cyberhong (Gast)


Lesenswert?

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

von cyberhong (Gast)


Lesenswert?

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....

von 900ss (900ss)


Lesenswert?

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
von Thomas F. (igel)


Lesenswert?

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.

von Εrnst B. (ernst)


Lesenswert?

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.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

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

von PittyJ (Gast)


Lesenswert?

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.

von Le X. (lex_91)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von 900ss (900ss)


Lesenswert?

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.

von Trollarzt (Gast)


Lesenswert?

cyberhong schrieb:
> ich möchte zu Lehrzwecken

zu Lernzwecken empfehle ichm Sie lernen zuerst korrekt zu schreiben,

Gute Besserung!

von 900ss (900ss)


Lesenswert?

Trollarzt schrieb:
> zu Lernzwecken empfehle ichm Sie lernen zuerst korrekt zu schreiben,
>
> Gute Besserung!

LOL! Gleichfalls.

von W.S. (Gast)


Lesenswert?

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.

von 900ss (900ss)


Lesenswert?

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?

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

Trollarzt schrieb:
> zuerst korrekt zu schreiben,

ahja:

Trollarzt schrieb:
> empfehle ichm Sie

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
Noch kein Account? Hier anmelden.