Guten Tag! Ich habe Probleme mit meiner RPi4 Cross-Compiler. Ich fange gerade erst mit dem RPi an und habe mich entsprechend ein bisschen eingelesen. => Embedded Linux mit Raspberry Pi und Co. v. Ralf Jesse. Das Buch ist schon ein eigentlich f. RPi B+. Also ein bisschen älter. Trotzdem ist es glaube ich eine gute Einführung. In dem Buch werden zwei Ansätze verfolgt. Einmal mit crosstool -ng und einmal mit Code::Blocks. Ich habe mich für Code::Blocks entschieden weil im Buch hauptsächlich damit gearbeitet wird. Wenn ich mit Code Blocks mein Programm "builden" möchte bekomme ich den Fehler: ld returned 1 exit status Build-Log: -------------- Build: Debug in Test2 (compiler: GNU GCC Compiler for ARM)--------------- arm-linux-gnueabihf-gcc -o bin/Debug/Test2 obj/Debug/main.o /usr/local/lib/libwiringPi.so /usr/local/lib/libwiringPi.so: file not recognized: File format not recognized collect2: error: ld returned 1 exit status Process terminated with status 1 (0 minute(s), 0 second(s)) 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) Ich hab es aber nochmal geprüft. Ich hab es genau so eingestellt wie im Buch. Unter LinkerSettings => Link libraries => /usr/local/lib/libwiringPi.so Was mich beim Installieren der Toolchain aber irgendwie gewundert hat ist das die Dateien oft mit BCM 2708 bezeichnet sind. Das ist ja eigentlich nicht der Prozessor vom RPi4. Der ist ja von einem älteren Modell. Die aktuelle Anleitung verweist aber auf die gleiche alte Toolchain. https://www.raspberrypi.org/documentation/linux/kernel/building.md Stehe ein bisschen auf dem Schlauch :D. Vielen Dank!
> /usr/local/lib/libwiringPi.so: file not recognized: File format not
recognized
Vom Pfad her sieht das aus wie eine Host Library, für Cross-Compiling
brauchst du aber ein Lib die zum Target passt.
Mirco G. schrieb: > /usr/local/lib/libwiringPi.so Keine Ahnung, wie du das eingerichtet hast, aber "/usr/local" nimmt man idR nicht für Dateien, die sich auf eine andere Platform beziehen. Mach mal ein
1 | readelf -h /usr/local/lib/libwiringPi.so |
und schau, ob das echt ein ARM-binary ist.
AVR schrieb im Beitrag #6212145: > Kompiliere doch einfach auf dem Pi. Richtig! Insbesondere der 4 hat dafür massig Power. MfG Klaus
Was für ein OS hast du auf dem Pi und auf dem PC? Auf Debian-basierten PC-OSen (z.B. Ubuntu, Mint) kann man zwar relativ leicht und sauber über den Paket-Manager den Cross-Compiler und Libraries installieren, aber wenn das nicht exakt die Versionen vom Pi sind kann es Probleme geben (und die Versionen müssen leider exakt die selben wie die für den Host sein). Yocto Linux hat da ein System für um exakt die Versionen des Targets zu nutzen, aber das kommt hier wohl eher nicht in Frage.
Heiko L. schrieb: > Keine Ahnung, wie du das eingerichtet hast, aber "/usr/local" nimmt man > idR nicht für Dateien, die sich auf eine andere Platform beziehen. Da ich die wiringpi Library nicht so wie im Buch oder auf http://wiringpi.com/download-and-install/ erläutert installieren konnte habe ich folgende Dateien von git runtergeladen: https://github.com/WiringPi/WiringPi Für die Programme sollte ich laut Buch einen Ordner "toolchain" unter /opt anlegen und die Dateien von Code Blocks und der Library hier ablegen. Dann hab ich die entsprechende Build Datei aus den wiringpi Dateien von git ausgeführt. Diese hat die Dateien dann wie im Buch beschrieben unter usr/local/lib und usr/local/include abgelegt. Heiko L. schrieb: > Mach mal einreadelf -h /usr/local/lib/libwiringPi.so > und schau, ob das echt ein ARM-binary ist.
1 | ELF Header: |
2 | Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |
3 | Class: ELF64 |
4 | Data: 2's complement, little endian |
5 | Version: 1 (current) |
6 | OS/ABI: UNIX - System V |
7 | ABI Version: 0 |
8 | Type: DYN (Shared object file) |
9 | Machine: Advanced Micro Devices X86-64 |
10 | Version: 0x1 |
11 | Entry point address: 0x4450 |
12 | Start of program headers: 64 (bytes into file) |
13 | Start of section headers: 89152 (bytes into file) |
14 | Flags: 0x0 |
15 | Size of this header: 64 (bytes) |
16 | Size of program headers: 56 (bytes) |
17 | Number of program headers: 7 |
18 | Size of section headers: 64 (bytes) |
19 | Number of section headers: 28 |
20 | Section header string table index: 27 |
AVR schrieb im Beitrag #6212145: > Kompiliere doch einfach auf dem Pi. Ich finde es entspannter wenn ich auf meinem normalen PC arbeiten kann. Programmierer schrieb: > Was für ein OS hast du auf dem Pi und auf dem PC? PC = Linux Mint 19.2 Tina Pi = Raspbian Linux 10 Programmierer schrieb: > Yocto Linux hat da ein System für um exakt die Versionen des > Targets zu nutzen, aber das kommt hier wohl eher nicht in Frage. Ich wollte halt erstmal ganz einfache Programme für den Pi schreiben um mit dem ganzen mal ein bisschen warm zu werden. Bin auch noch nicht lange mit Linux unterwegs. Was haltet ihr denn von crosstool -ng? Das sieht irgendwie ziemlich kompliziert aus finde ich. Ich lese mich da auch gerne selber ein. Der RPi ist doch so populär da müsste es doch was gescheites geben oder? Zu meiner Verwunderung konnte ich halt irgendwie nichts finden. Vielen Dank! Mirco
Mirco G. schrieb: > Machine: Advanced Micro Devices X86-64 Also ist das definitiv keine ARM-Lib. Vermutlich soll man das eigentlich auf dem Pi selbst kompilieren und installieren. Um ein Programm, dass die lib verwendet, cross zu kompilieren (crunchy) brauchst du Header und ein Binary zum linken. Die Header scheinst du ja rumfliegen zu haben. Was das Binary angeht ist es wohl am einfachsten, die libwiringPi.so von einem Pi runterzukopieren und dagegen zu linken.
Heiko L. schrieb: > Um ein Programm, dass die lib verwendet, cross zu kompilieren (crunchy) > brauchst du Header und ein Binary zum linken. Mich hat das mit den Libraries ein bisschen verwirrt. Ich war mir unklar warum ich überhaupt zwei verschiedene habe einmal eine .so und einmal eine .h. Ich habe bisher nur mit normalen Controllern und den entsprechenden Hersteller IDEs gearbeitet. Nach ein wenig rumsuchen bin ich zu folgendem Ergebnis gekommen: Ich hab mir die wiringP.h mal angeschaut und dabei ist mir aufgefallen das die Funktionen hauptsächlich nur als extern definiert wurden => es muss ein anderes File geben welches diese definiert. Deswegen habe ich mir die Funktionen der libwiringPi.so mal mit objdump -T ausgeben lassen. Dabei kommt dann folgendes raus.
1 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 puts |
2 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 setsockopt |
3 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 pthread_setschedparam |
4 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 fcntl |
5 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 clock_gettime |
6 | 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 write |
Die als extern definierten Funktionen der .h kommen also aus der .so. Da Du es als Binary bezeichnet hast nehme ich mal an das die .so schon compilierte Teilfunktionen enthält. Vorcompiliert wird vermutlich damit das compilieren auf einem RPi nicht so lange dauert? Ansonsten sehe ich darin nämlich keinen Sinn :D. Warum muss ich jetzt aber nochmal gesondert linken? Eigentlich linked mir meine IDE in meinem Fall Code:Blocks doch nachher alles was ich brauche zusammen oder? Heiko L. schrieb: > Was das Binary angeht ist es wohl am einfachsten, > die libwiringPi.so von einem Pi runterzukopieren und dagegen zu linken. Wo soll ich die dann ablegen wenn usr/local/ nicht in ordnung ist? Möchte darauf vielleicht noch jemand eingehen? => Mirco G. schrieb: > Was mich beim Installieren der Toolchain aber irgendwie gewundert hat > ist das die Dateien oft mit BCM 2708 bezeichnet sind. Das ist ja > eigentlich nicht der Prozessor vom RPi4. Der ist ja von einem älteren > Modell. > > Die aktuelle Anleitung verweist aber auf die gleiche alte Toolchain. > > https://www.raspberrypi.org/documentation/linux/kernel/building.md Vielen Dank!
Mirco G. schrieb: > Wo soll ich die dann ablegen wenn usr/local/ nicht in ordnung ist? Das ist im Prinzip egal. Google: sysroot Mirco G. schrieb: > Warum muss ich jetzt aber nochmal gesondert linken? Das ist eine exzellente Frage. Touche. Dafür gibt es, glaube ich, eigentlich keine zwingende technische Notwendigkeit, das ist nur so eine Prüfung, dass nachher im Programm alles definiert ist und zur Generierung von Dependency-Einträgen verwendet wird. Zu deinen restlichen allgemeinen Fragen, würde ich dich bitten, das weitere Internet zu konsultieren, was .so und .h Dateien sind usw. Da gibt es so viele Erklärungen...
Mirco G. schrieb: > Ich war mir unklar warum ich überhaupt zwei verschiedene > habe einmal eine .so und einmal eine .h. In der .h ist die Schnittstelle zur Bibliothek definiert (d.h. welche Funktionen gibt es, wie werden sie aufgerufen). Die benutzt der Compiler, um den passenden Aufrufcode zu generieren. Die .so ist ein shared object und enthält den fertigen Binärcode, der aber noch nicht vollständig gelinkt ist. Mirco G. schrieb: > Da Du es als Binary bezeichnet hast nehme ich mal an das > die .so schon compilierte Teilfunktionen enthält. Das ist alles schon vollständig fertig compiliert (zumindest die Funktionen, die da drin sind). Da sind nur zusätzliche Informationen drin, die man braucht, um die Datei in den Speicher eines anderen Programmes laden zu können. Mirco G. schrieb: > Vorcompiliert wird vermutlich damit das compilieren auf einem RPi nicht > so lange dauert? Ansonsten sehe ich darin nämlich keinen Sinn :D. Nein, das ist aber ein nützlicher Effekt. Eine shared library (im Gegensatz zu einer static library) bleibt im Dateisystem immer getrennt vom eigentlichen Programm. Wenn du das Programm startest, lädt der dynamische Linker (ld.so) alle benötigten .so-Dateien in den Speicher und passt alle Funktionsaufrufe des Programms so an, dass die auf die richtigen Adressen zeigen. Das heißt, dass (a) mehrere Programme die gleiche Datei nutzen können, was Plattenplatz spart; (b) mehrere Programme die gleiche Datei im RAM nutzen können (zumindest den readonly-Anteil, also v.a. Code), das spart RAM; (c) du die Bibliothek getrennt vom Programm aktualisieren kannst. Der dritte Punkt ist interessant, denn damit kannst du einerseits für jeden Raspberry Pi eine spezielle Bibliothek anbieten, ohne dein Programm ändern zu müssen - andererseits brauchst du, wenn die Bibliothek einen Fehler weniger hat, dein Programm nicht neu zu linken. Unter Windows gibt es das gleiche Konzept und heißt dort DLL. Mirco G. schrieb: > Warum muss ich jetzt aber nochmal gesondert linken? In deinem Programm steht drin, welche .so-Dateien nötig sind, welche Funktionen daraus benutzt werden, und wo die Datei zu finden ist. Diese Informationen benutzt ld.so, um das Programm zu starten. (Stark vereinfacht, das ganze.)
Ich habe jetzt die wiringPi.so und wiringPi.h von meinem RPi genommen. Jetzt habe ich beim compilieren keine Fehler mehr. Ich hab an Pin 17 eine LED angeschlossen die ich auf dem Pi auch mit dem Terminal ansteuern kann. Auf meinen Compilierten Code reagiert die aber nicht. Das hier ist mein Code
1 | #include <wiringPi.h> |
2 | #include <stdio.h> |
3 | |
4 | int main(void) |
5 | { |
6 | wiringPiSetup(); |
7 | pinMode(17,OUTPUT); |
8 | |
9 | while(1) |
10 | { |
11 | digitalWrite(17,HIGH); |
12 | delay(500); |
13 | digitalWrite(17,LOW); |
14 | delay(500); |
15 | |
16 | printf("hallo\n"); |
17 | } |
18 | |
19 | return 0; |
20 | |
21 | } |
Das Printf gibt er mir auf dem Pi auch richtig im Terminal aus. Ich hab aber ehrlich gesagt keine Ahnung wie ich jetzt rausfinden kann woran es liegt. Kann mir da jemand helfen? DANKE!
Hat sich erledigt. Ich musste die wiringPi lib nochmal updaten auf 2.52. Nachtrag: Was mich aber verwundert ist warum jetzt der auf meinem PC compilierte Code auf dem Pi funktioniert obwohl ich die wiringPi.so und wiringPi.h von der 2.5 Version zum Compilieren verwendet habe :D. An meinem Compilierten File hat sich ja nichts geändert :D.
:
Bearbeitet durch User
Mirco G. schrieb: > Ich finde es entspannter wenn ich auf meinem normalen PC arbeiten kann. ssh/putty und wenn es grafisch sein soll, noch einen X-Server dazu.
Mirco G. schrieb: > Was mich aber verwundert ist warum jetzt der auf meinem PC compilierte > Code auf dem Pi funktioniert obwohl ich die wiringPi.so und wiringPi.h > von der 2.5 Version zum Compilieren verwendet habe :D. In der wiringPi.h sind nur die Prototypen enthalten. Die ändern sich bei unterschiedlichen Bibliotheksversionen nicht groß. Ebenfalls ändern sich die Funktionen einer Bibliothek nur selten. Oft sind es Bugfixes, Erweiterungen der vorhandenen oder komplett neue Funktionen. Daher ist es Deinem Programm fast egal, welche Bibliothek verwendet wird.
Du musst noch vielen lernen. Mach Dich doch erstmal über das generelle Prinzip eines dynamischen Linkers, insbesondere unter Linux, vertraut. Es gibt da nämlich ein paar Konventionen und Festlegungen damit man eben gerade die Libraries gegen neuere Versionen tauschen kann ohne das vorhandene Programm neu kompilieren zu müssen. Warum du allerdings dein Programm unbedingt per Cross-Compiler übersetzen willst ist mir schleierhaft. Ein vollständige, zu dem Raspi-System passende Cross-Compile Umgebungen aufzusetzen ist nicht trivial, eine ungünstig oder unabsichtlich falsch gesetzte Compileroption, eventuell einfach durch irrtümliche Nutzung von pkgconfig und Du Kompilierst dein Programm gegen Header von deinem PC System aber linkst gegen die Raspi Libs. Warum arbeitest Du nicht direkt auf dem Raspi? Der hat Power genug dafür. Man kann auch vom PC aus remote per SSH auf dem Raspi arbeiten. Ganz intuitiv wird das mit Visual Studio Code und den Remote Erweiterungen. Da arbeitet man in der Gui am PC aber alle Aktionen werden transparent per SSH auf dem Zielsystem ausgeführt. Ist wirklich eine tolle Sache.
Andreas M. schrieb: > Du musst noch vielen lernen. Da gebe ich dir recht :). Andreas M. schrieb: > Mach Dich doch erstmal über das generelle > Prinzip eines dynamischen Linkers, insbesondere unter Linux, vertraut. Ich lese mich ja parallel ein. Von einfachem lesen wird man aber oft nicht schlau. Deswegen arbeite ich nebenbei immer schon praktisch. Auch wenn dann oft fragen aufkommen. Andreas M. schrieb: > Warum du allerdings dein Programm unbedingt per Cross-Compiler > übersetzen willst ist mir schleierhaft. Ich habe das nur gemacht weil das in meinem Buch so vorgeschlagen war. Ich hab vor einem Jahr schon ein ganz kleines bisschen über ssh gearbeitet. Deswegen wollte ich es mal ausprobieren. Hab auch ein wenig was über Cross Compiler gelernt den Rest mache ich jetzt auch direkt auf dem Pi. Andreas M. schrieb: > Ganz intuitiv wird das mit Visual Studio Code und den Remote > Erweiterungen. Da arbeitet man in der Gui am PC aber alle Aktionen > werden transparent per SSH auf dem Zielsystem ausgeführt. Ist wirklich > eine tolle Sache. Schaue ich mir mal an. Danke!
Ich würde ganz gerne zumindest die GPIO Bedienung verstehen. Bei einem uC werden die GPIOs ja über die entsprechenden Register angesteuert. Das wird beim RPi ja vermutlich nicht anders sein. https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf Die Registerbeschreibung kann ich mit der wiringPi.h aber nicht nachverfolgen. Die Funktionen müssten also in der wiringPi.so stehen. Davon kann ich mir ja aber nur die entsprechenden Funktionsnamen ausgeben lassen. Ich habe hier ein paar Beispiele für die Ansteuerung gefunden: https://elinux.org/RPi_GPIO_Code_Samples Das erste Beispiel für den direkten Registezugriff ist für mich unverständlich, obwohl ich es bei "norameln" uC schon mehrfach gemacht habe. Bei dem Beispiel "Zugriff über sysfs" wird das sysfs Interface irgendwie ein bisschen mit C missbraucht. Das ist ja vermutlich auch nicht Sinn und Zweck oder? Ich bin mir auch unsicher ob und wo der Kernel beim Ausführen meines compilierten binarys (von oben) ins Spiel kommt. Wird mithilfe von wiringPi direkt an die Register geschrieben oder werden irgendwelche Gerätedatein dadurch verändert. Diese Wissenslücke kann ich gerade irgendwie nicht schließen. Ich hab auch schon ordentlich gegoogelt. Ich konnte keine Quelle finden die darauf so detailliert eingeht. Kurz gesagt: Wie ist der grobe Ablauf bei der GPIO Bedienung von meinem Sourcecode zur Registerbeschriebung im Controller. Wo kommt da mein Betriebssystem und die entsprechende Gerätedatei ins Spiel. VIELEN DANK! Mirco
Mirco G. schrieb: > Ich würde ganz gerne zumindest die GPIO Bedienung verstehen. Bei einem > uC werden die GPIOs ja über die entsprechenden Register angesteuert. Das > wird beim RPi ja vermutlich nicht anders sein. Ja ist das gleich Prinzip, mit dem Unterschied das du einen Linux-Kernel hast und der SoC auch noch eine MMU. Der Linux-Kernel erlaubt einer Anwendung normalerweise nicht, einfach irgendwo im Addressraum zu lesen und zu schreiben. Dazu kommt, dass Dein Programm unter Linux in einem virtuellen Addressraum lebt. D.h. Für jedes Programm was im Linux läuft führt der Linux-Kernel eine Tabelle die eine Speicher-Addresse im Programm (Virtuelle Addresse) auf eine Physikalische Addresse abbildet. (Natürlich nicht für jede Speicherzelle einzeln aber in Blöcken/Gruppen) Das ist auch der Grund, warum bei zwei Programmen unter Linux (und auch unter Windows) man unter der selben Speicheraddresse meist unterschiedliche Daten findet, denn für jedes Program wird diese gleiche virtuelle Addresse auf einen anderen physikalischen Speicherbereich abgebildet. Man kann das natürlich auch umgekehrt benutzen um zwei Programmen unter (eventuell unterschiedlichen) virtuellen Addressen Zugriff auf den gleichen Physikalischen Speicher zu ermöglich. (Genau das passiert unter Linux wenn zwei Programme die gleiche Library laden, die liegt dann effektiv nur einmal im Speicher) Diese Umrechnung von Virtueller nach Physikalischer Addresse macht die MMU. (Und noch ein bischen mehr) > Die Registerbeschreibung kann ich mit der wiringPi.h aber nicht > nachverfolgen. Die Funktionen müssten also in der wiringPi.so stehen. Ja, normalerweise könntest du in den Quellcode schauen, das scheint aber gerade down zu sein https://git.drogon.net/ > Ich habe hier ein paar Beispiele für die Ansteuerung gefunden: > > https://elinux.org/RPi_GPIO_Code_Samples > > Das erste Beispiel für den direkten Registezugriff ist für mich > unverständlich, obwohl ich es bei "norameln" uC schon mehrfach gemacht > habe. Naja, wie oben gesagt, erlaubt der Linux-Kernel nicht jedem x-Beliebigen Programm irgendwo in den Speicher zu schreiben. Dazu kommt, das für Dein Program die MMU so eingestellt werden muss, dass der Physikalische Speicherbereich der GPIO Peripherie in den virtuellen Addressraum deines Programmes eingeblendet wird. Dass passiert in dem o.g. Beispiel durch die Kombination von open("/dev/mem"), mmap() (und close) "/dev/mem" ist ein sogenanntes device-file. (eine schnittstelle zum kernel.) Der mmap() Aufruf wird an den Kernel-Treiber der an "/dev/mem" angebunden ist weitergeleitet und dieser macht dann was. In diesem Fall hier sagt der mmap-Aufruf "Blende bitte BLOCK_SIZE Bytes ab der physikalischen Speicheraddresse GPIO_BASE in meinem virtuellen Speicher ein". Der Rückgabewert der Funktion ist die Speicheraddresse im Programm an der dann auf den Physikalischen Speicher von GPIO_BASE bis GPIO_BASE+BLOCK_SIZE zugegriffen werden kann und damit direkt auf den GPIO Peripherie Block. Achtung: Zugriffe auf /dev/mem funktionieren normalerweise nur, wenn das Programm als "root" läuft. Ich weis jetzt nicht ob es da bei RPi Ausnahmen gibt. > Bei dem Beispiel "Zugriff über sysfs" wird das sysfs Interface irgendwie > ein bisschen mit C missbraucht. Das ist ja vermutlich auch nicht Sinn > und Zweck oder? Das sysfs ist einfach eine weitere Schnittstelle zu den Kerneltreibern. Der Vorteil ist, das diese sehr einfach benutzt werden kann. Man öffnet einfach die Datei, schreibt einen "Befehl" rein und schließt sie wieder. (Oder liest daraus informationen) Der entsprechende Treiber im Kernel erhält dann den Befehl und führt ihn aus oder erzeugt die gewünschten Daten. Durch diesen einfachen Mechanismus kann man das auch aus Skripten heraus gut benutzen. > Ich bin mir auch unsicher ob und wo der Kernel beim Ausführen meines > compilierten binarys (von oben) ins Spiel kommt. Wird mithilfe von > wiringPi direkt an die Register geschrieben oder werden irgendwelche Da müsste man sich den Quellcode von wiringPi anschauen. > Gerätedatein dadurch verändert. Diese Wissenslücke kann ich gerade > irgendwie nicht schließen. > > Ich hab auch schon ordentlich gegoogelt. Ich konnte keine Quelle finden > die darauf so detailliert eingeht. Ja, das wollen die meisten heute auch gar nicht mehr wissen; "gibt ja ne fertige Library". Libraries sind nicht schlecht, ich bin aber auch dafür das man die Grundlagen verstehen sollte. Hilft beim Fehlersuchen. Hier ist übrigens der Quellcode des Kernel Treiber für die "/dev/mem": https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/mem.c?h=v5.6 Wenn du in deinem Program "mmap" für "/dev/mem" aufrufst, dann kommst Du dort in der Funktion "mmap_mem" an. mmap() kann man auch mit normalen Dateien benutzen. Dann kann man einfach über Zeiger auf den Dateiinhalt zugreifen. Die Datei wird dafür zunächst gar nicht geladen, sondern die MMU so eingestellt, das beim ersten Zugriff auf den Virtuellen Speicher der Kernel ein Signal bekommt das der betreffende Bereich angefordert wurde und mit Daten gefüllt werden müsste. Erst dann werden die Daten von der Festplatte in den Ram geladen. Mit dem gleichen Mechanismus implementiert der Kernel auch den Auslagerungsspeicher, d.h. die Möglichkeit ein laufendes Programm auf der Festplatte zu parken.
Mirco G. schrieb: > Das erste Beispiel für den direkten Registezugriff ist für mich > unverständlich, obwohl ich es bei "norameln" uC schon mehrfach gemacht > habe. Was verstehst du daran nicht? Pointer-Operationen in C sind dir geläufig? Mirco G. schrieb: > Ich konnte keine Quelle finden > die darauf so detailliert eingeht. Die erste Quelle sollte das Datenblatt des Bausteins sein, den du ansprechen willst.
Mirco G. schrieb: > Ich würde ganz gerne zumindest die GPIO Bedienung verstehen. > Bei einem uC werden die GPIOs ja über die entsprechenden > Register angesteuert. Das wird beim RPi ja vermutlich nicht > anders sein. Das stimmt. Aber auf dem Raspberry Pi läuft ein richtiges Betriebssystem, mit Speicherschutz, allgemeiner Treiberunterstützung und ordentlichen Programmierschnittstellen. Man kann direkt auf den Registern rumschreiben (siehe /dev/mem). Aber es ist viel einfacher, fertige Treiber zu benutzen. Das gilt insbesondere dann, wenn die Dinge komplizierter werden, z.B. für Ethernet- oder CAN-Hardware. > Die Registerbeschreibung kann ich mit der wiringPi.h > aber nicht nachverfolgen. In einer Headerdatei steht nur die API. Das ist der Teil, den du brauchst, um die Bibliothek benutzen zu können, nicht wie sie funktioniert. Das ist nur die Bedienungsanleitung. > Die Funktionen müssten also in der wiringPi.so stehen. Ja, aber schon fertig kompiliert als Binärcode. Wenn du wissen willst, wie das im Detail funktioniert, dann musst du in den Code der Bibliothek schauen. Den gibt's z.B. auf Github: https://github.com/WiringPi/WiringPi (und die Originalbibliothek wird nicht mehr weiterentwickelt, weil gewisse Menschen Arschlöcher sind). > Das erste Beispiel für den direkten Registezugriff ist > für mich unverständlich, obwohl ich es bei "norameln" uC > schon mehrfach gemacht habe. Wenn du keine MMU hast, dann ist die Adresse 0x12345678 irgendwo im physischen Adressraum und wenn da zufällig dein Register ist, dann kannst du darauf zugreifen. Wenn du eine MMU hast, dann ist die Adresse 0x12345678 irgendwo im Adressraum deiner Anwendung, und da ist garantiert kein Register, wenn du die MMU nicht vorher angewiesen hast, das dorthin zu mappen. Deswegen brauchst du den /dev/mem und mmap()-Tanz. > Bei dem Beispiel "Zugriff über sysfs" wird das sysfs Interface > irgendwie ein bisschen mit C missbraucht. Das ist ja vermutlich > auch nicht Sinn und Zweck oder? Sysfs ist nunmal eine Kernel-API für das GPIO-Subsystem. Wenn die GPIOs dem Kernel bekannt sind, dann kannst du über sysfs darauf zugreifen. Das soll schon so, auch wenn sysfs keine angenehme C-Schnittstelle ist. Dafür funktioniert sie auch mit Shellscripts, Perl, Rust sowie jedem anderen Kram, der Dateien lesen und schreiben kann... > Ich bin mir auch unsicher ob und wo der Kernel beim Ausführen meines > compilierten binarys (von oben) ins Spiel kommt. Wenn du WiringPi benutzt, dann hängen die Details von der Implementation von WiringPi ab. Du kannst auch eine andere Bibliothek mit der gleichen API schreiben (d.h. die würde dann die gleiche wiringpi.h benutzen), die das ganz anders macht. > Kurz gesagt: Wie ist der grobe Ablauf bei der GPIO Bedienung von meinem > Sourcecode zur Registerbeschriebung im Controller. Wo kommt da mein > Betriebssystem und die entsprechende Gerätedatei ins Spiel. Sinnvollerweise würde ich mich von der Hardware lösen. Direkte Registerzugriffe macht man unter Linux einfach nicht, das lässt man Linux machen. Und das heißt, dass du dich in "GPIOs unter Linux" einarbeitest. Hat den Vorteil, dass es auf jedem beliebigen Gerät gleich funktioniert. Zumindest von "mein Programm will was tun" und "der Hardwaretreiber tut jetzt was". Und wenn du dann noch weitersuchen willst, dann schaust du in die Linux-Treiber - die meisten Kerneltreiber sind halbwegs lesbar. Inzwischen kann Linux auch "besser als sysfs", siehe z.B. hier: https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/ Mirco G. schrieb: > Ich konnte keine Quelle finden die darauf so detailliert eingeht. Weil ein Raspberry Pi im Prinzip nichts anderes ist als ein normaler Linux-Computer auch. Die Erklärungen findet man an anderer Stelle - man muss nicht speziell "Linux auf Raspberry Pi" erklären, weil es nicht speziell ist.
Mirco G. schrieb: > Wird mithilfe von wiringPi direkt an die Register geschrieben > oder werden irgendwelche Gerätedatein dadurch verändert. Ich habe gerade ein bisschen in WiringPi/wiringPi.c gesurft. Die Bibliothek liest die Chipversion aus /proc/cpuinfo aus, nutzt /dev/mem (oder /dev/gpiomem, wenn keine Zugriffsrechte) für direkten Registerzugriff und sysfs für Interrupts. Außerdem implementiert WiringPi ziemlich viele Chiptreiber selbst, obwohl der Kernel selbst wahrscheinlich viele Treiber schon enthält. Ist halt einfacher.
Beitrag #6216227 wurde vom Autor gelöscht.
Vielen Dank Andreas und Svenska :). Super das Ihr euch die Zeit genommen habt das zu erläutern! Ist nicht selbstverständlich :). S. R. schrieb: > Sinnvollerweise würde ich mich von der Hardware lösen. Direkte > Registerzugriffe macht man unter Linux einfach nicht, das lässt man > Linux machen. Und das heißt, dass du dich in "GPIOs unter Linux" > einarbeitest. Das möchte ich auch. Ich finde es aber immer ganz gut zumindest einfache Aufgaben wie die GPIO Bedienung zu verstehen. Durch eure Erläuterungen hab ich vieles besser verstanden. Jetzt kann ich mit ruhigem Gewissen entfernter von der Hardware arbeiten, weil ich zumindest das Grundprinzip ein wenig durchblickt habe:). Vielen vielen Dank!
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.