Forum: Mikrocontroller und Digitale Elektronik Device Driver für uCLinux auf dem STM32f103ze


von Christopher Biel (Gast)


Lesenswert?

Hi,
ich bin derzeit dabei einen Analyseserver auf einem STM32F103ZE 
aufzusetzen der Daten vom CAN-Bus lesen soll. Als Betriebssystem dient 
uCLinux(2.6.x). Hierfür benötige ich bekanntlich einen Treiber, damit 
ich den CAN-Bus richtig nutzen kann als Device (also zb als /dev/can1 ).

Zunächst wie es bisher ist:
Derzeit ist es so, dass ich die Standardlibrary von ST genommen habe, in 
meine Anwendung eingebunden haben und es nach einigen Änderungen 
geschafft habe den CAN-Bus darüber in meiner Anwendung zu nutzen. Das 
blöde dabei ist, dass es nicht dem Standard entspricht, da einfach ein 
paar .h eingebunden sind und dann am Ende alles zusammengelinkt wird.

Was ich möchte:
Ich hätte es nun gerne so, dass ich Device im dev Verzeichnis habe, 
beispielsweise "/dev/can1" das ich dann ganz normal per open(/dev/can1) 
ansprechen kann und direkt darüber schreiben und lesen kann.
Ich habe mir bereits angesehen wie das mit den simple-gpio's gereglt ist 
(für die die es nicht direkt kennen: es gibt eine Beispielanwendung von 
ST "Led_Show" die diesen Treiber benutzt und wo über open(), write(), 
read() die einzelnen LEDs angesprochen werden können).
Grundsätzlich habe ich auch kein Problem damit das zu verstehen und 
könnte den Treiber selbst, wohl auch schreiben.

Nun das Problem:
Unter Linux werden, wie o.g., Device-Nodes im dev Verzeichnis erstellt 
um diese dann anzusprechen. Damit eine solche Device-Node auch weiß, was 
es denn überhaupt ist und welchen Treiber es benutzen soll, gibt es die 
MAJOR und MINOR Nummern in Linux.
Und hier geht das Problem los. Ich glaube verstanden zu haben, dass 
jeder Treiber eine eindeutige MAJOR Nummer und jedes Gerät eine 
eindeutige MINOR Nummer, damit der Treiber beim verwalten von mehreren 
Devices diese auseinanderhalten kann.
Was aber nirgendwo erklärt ist und auch nirgendwo im uCLinux 
(Beispiel-)Code zu finden ist, ist "wie" setze ich die MAJOR und MINOR 
Nummer.
In den beiliegenden Beispielen scheint es so zu sein, dass diese 
automatisch vergeben werden über die Funktion 
"platform_register_driver()". Interessanterweise ist es aber dann so, 
dass z.B. die schon oben erwähnte gpio-Treiber immer die MAJOR Nr. 253 
hat. Dies scheint aber nirgendwo vermerkt zu sein. Und dadurch kann ich 
meinem Devise, das ich anlege, nicht sagen welchen Treiber es benutzen 
soll, da man dafür diese Nummer wissen muss, die man nebenbei auch 
nirgendwo nachsehen kann.

Meine Frage(n) nun:
Weiß irgendjemand wie man die MAJOR Nr. setzen kann?
Wenn ja, woher weißt du/er/sie das?
Gibt es ein entsprechenden Beispiel o.ä.?

Wenn ihr weitere Infos, wie Sourcen oder sowas benötigt, dann einfach 
bescheid sagen.

Danke schonmal und hoffe mir kann jemand helfen
Christopher

von Björn K. (terminar)


Lesenswert?

Hi,

mal eingeworfen, ein paar Ideen zu dem Thema:

http://www.kernel.org/doc/Documentation/devices.txt

Eine gute Stelle für Dokumentationen zum Linux-Kernel findet man je nach 
Installation eines Standard-Linux Systems unter 
/usr/src/linux/Documentation oder unter dem Link oben. Die Kernel 
Sourcen beinhalten diese Infos zum großen Teil.

Documentation/driver-model/platform.txt bzw die anderen Dateien in dem 
Ordner sind vielleicht auch informativ.

Ich habe selbst noch nicht unter ucLinux entwickelt, gehe aber davon aus 
das der Grundkernel sich wenig verändert hat und auch das Treiber-Modell 
ähnlich aufgebaut ist.

Daher hilft vielleicht ein Blick ins LDD,
http://lwn.net/Kernel/LDD3/ oder unter 
http://www.makelinux.net/ldd3/chp-3-sect-2.shtml

Ich würde an deiner Stelle im Linux Kernel Source etwas wühlen und mir 
Beispielcode anschauen. Unter drivers/char/cs5535_gpio.c ist ein 
Beispiel, wo die major number per Modulparameter übergeben werden kann.

register_chrdev_region
alloc_chrdev_region
MKDEV(...

sind Suchbegriffe die helfen könnten. drivers/char/vt.c scheint auch ein 
gutes Beispiel zu sein.

Ich kann dir aber leider nicht sagen, inwieweit der ucLinux Kernel vom 
normalen Linux-Kernel abweicht.

Aber selbst dann mein Tipp: andere Treibersourcen anschauen.

Bis denn
Björn

von Imon (Gast)


Lesenswert?

Christopher Biel schrieb:
> Hi,
> ich bin derzeit dabei einen Analyseserver auf einem STM32F103ZE
> aufzusetzen der Daten vom CAN-Bus lesen soll. Als Betriebssystem dient
> uCLinux(2.6.x). Hierfür benötige ich bekanntlich einen Treiber, damit
> ich den CAN-Bus richtig nutzen kann als Device (also zb als /dev/can1 ).
>

Okay das ist dein Vorhaben die Buzzwords Hierzu sind CANopen und 
Can4Linux,
bin mir im Augenblick nicht sicher was besser geeignet ist, allerdings 
würde ich hier mal einen Blick drauf Werfen bevor du das Rad neu 
erfindest. Das hätte dann auch denn Vorteil das deine Analyseserver 
Hardware unabhängig wäre weil die beiden genannten Frameworks von der 
realen Hardware abstrahieren.

> Zunächst wie es bisher ist:
> Derzeit ist es so, dass ich die Standardlibrary von ST genommen habe, in
> meine Anwendung eingebunden haben und es nach einigen Änderungen
> geschafft habe den CAN-Bus darüber in meiner Anwendung zu nutzen. Das
> blöde dabei ist, dass es nicht dem Standard entspricht, da einfach ein
> paar .h eingebunden sind und dann am Ende alles zusammengelinkt wird.
>

das ist doch garnicht so schlecht, auch wenn ich stark den verdacht habe
das es nur läuft weil du ein NOMMU System hast ( µClinux ist nommu, auch 
wenn der Prozessor eine hat) und dir aus denn grund Wahrscheinlich 
keiner auf die Finger Klopft wenn du Hard auf igendwelche Adressen 
zugreifst.


> Was ich möchte:
> Ich hätte es nun gerne so, dass ich Device im dev Verzeichnis habe,
> beispielsweise "/dev/can1" das ich dann ganz normal per open(/dev/can1)
> ansprechen kann und direkt darüber schreiben und lesen kann.

guter Plan wenn das mit den OpenCAN und CAN4Linux nichts wird mach hier 
weiter ;-)

> Ich habe mir bereits angesehen wie das mit den simple-gpio's gereglt ist
> (für die die es nicht direkt kennen: es gibt eine Beispielanwendung von
> ST "Led_Show" die diesen Treiber benutzt und wo über open(), write(),
> read() die einzelnen LEDs angesprochen werden können).

argg der simple-gpio Treiber dnen du ansprichst ist nur in µClinux 
vorhanden, recht eigenwillig entwickelt und wird hoffentlich bald 
entsorgt. Solltest denn also nicht unbedingt als Vorlage nutzen.

> Grundsätzlich habe ich auch kein Problem damit das zu verstehen und
> könnte den Treiber selbst, wohl auch schreiben.
>
> Nun das Problem:
> Unter Linux werden, wie o.g., Device-Nodes im dev Verzeichnis erstellt
> um diese dann anzusprechen. Damit eine solche Device-Node auch weiß, was
> es denn überhaupt ist und welchen Treiber es benutzen soll, gibt es die
> MAJOR und MINOR Nummern in Linux.
> Und hier geht das Problem los. Ich glaube verstanden zu haben, dass
> jeder Treiber eine eindeutige MAJOR Nummer und jedes Gerät eine
> eindeutige MINOR Nummer, damit der Treiber beim verwalten von mehreren
> Devices diese auseinanderhalten kann.

das ist nur noch bedingt so, da die Kernelentwickler das Problem sehen 
das, die Major Nummern ausgehen könnten. Werden moderne Treiber so 
entwickelt das sie diese Nummern Dynamisch erhalten und nicht mehr 
vorgeben werden.

Stichwort platformdevice. um das anlegen des Device node unter /dev 
kümmert sich dann ein Dämon wie udev oder mdev ( wobei es meisten udev 
ist)

> Was aber nirgendwo erklärt ist und auch nirgendwo im uCLinux
> (Beispiel-)Code zu finden ist, ist "wie" setze ich die MAJOR und MINOR
> Nummer.

stimmt die sind ja auch an aussterben. Ein wenig Information zu den 
Thema findet sich in der Datei Documentation/devices.txt dort erfährst 
du zum Beispiel das der Major bereich 91 bei char devices für CAN 
Reserviert ist und die Minor Nummer die Can devices Hoch zählt also 
/dev/can0 hat Major =91 und Minor=0; /dev/can1 Major=91, Minor= 1 etc.

Zum setzen der Node gibt es das Makkro MKDEV, such dir einfach einen 
Treiber unter device/char/* als Beispiel und versuche zu verstehen was 
dort gemacht wird.  drivers/input/joydev.c ist zum Beispiel so ein 
Treiber.

> In den beiliegenden Beispielen scheint es so zu sein, dass diese
> automatisch vergeben werden über die Funktion
> "platform_register_driver()". Interessanterweise ist es aber dann so,
> dass z.B. die schon oben erwähnte gpio-Treiber immer die MAJOR Nr. 253
> hat. Dies scheint aber nirgendwo vermerkt zu sein.

Das kann sich aber ändern, ich denke du hast nur den Vorteil das dein 
System beim Starten wenig Fluktuation hat weswegen es zufällig stabil 
ist. Wie gesagt für das anlegen der passenden devicenode unter /dev gibt 
es ein Dämon, welcher das ist, wird denn Kernel über 
/proc/sys/kernel/hotplug mitgeteilt, dieser wird dann getriggert wenn 
ein Device geladen oder entladen wird, der kümmert sich um dann um den 
passenden /dev Eintrag.

> Und dadurch kann ich
> meinem Devise, das ich anlege, nicht sagen welchen Treiber es benutzen
> soll, da man dafür diese Nummer wissen muss, die man nebenbei auch
> nirgendwo nachsehen kann.

falsch entweder du schriebst ein Treiber wo du explizit die Major und 
Minor Nummer setzt dann kannst du das device statisch mit
1
 mknod name c Major Minor

als root anlegen. oder du nutz die Dynamisch Vergabe der Node über die
informiert dich dein Kernel über die Datei /proc/devices

wo er dir sagt welche Major Nummer welches Device bekommen hat.

> Meine Frage(n) nun:
> Weiß irgendjemand wie man die MAJOR Nr. setzen kann?

ja sie oben

> Wenn ja, woher weißt du/er/sie das?

aus denn Buch Linux Device Driver und der täglichen Erfahrung. :-)

> Gibt es ein entsprechenden Beispiel o.ä.?

siehe dir die Treiber an, welche bei ein linux dabei sind, such nach
Begriffen wie CAN4LINUX, SocketCAN µCLinux und wenn das nichts hilft 
stick deine eigene lösung such dir ein Char device unter /device/char in 
dein Kernel Code und klaue von dort, Ausserdem solltest du dir das 
Verzeichnis Dokumentation ansehen, das Oben genannte Buch in der 3 
Ausgabe (davor ist zu alt) ist auch nicht schlecht sind die Webseite 
Kernelnewbie und das µClinux Forum.

> Wenn ihr weitere Infos, wie Sourcen oder sowas benötigt, dann einfach
> bescheid sagen.
>
 oder and

> Danke schonmal und hoffe mir kann jemand helfen
> Christopher

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.