Hallo, habe ein Problem mit der Einbindung von *.S Dateien in mein Raspberry Pi C-Projekt. (gcc Compiler). Ich möchte Versuchen den System Timer zu verwenden (Interrupt Auslösung alle paar ms) wie im folgenden Projekt gemacht wurde: Die Assembler Datein stammen aus: https://github.com/dwelch67/raspberrypi/tree/master/blinker07 kleiner Auszug: extern void PUT32 ( unsigned int, unsigned int ); extern unsigned int GET32 ( unsigned int ); . . . ra=GET32(GPFSEL1); Ich muss nun die Funktionen GET32 und PUT32 aufrufen welche anscheinend in einem Assembler File vorliegen. Ich habe leider keinen Plan wie ich z.B. die Datei vectors.S (dort kommt GET32 und PUT32 vor) in mein Makefile einbinden muss. Mein Makefile sieht momentan so aus: CC=gcc CFLAGS=-I. LDFLAGS = -L/usr/local/lib INCLUDE = -I/usr/local/include AS = nasm ASFLAGS = -f coff DEPS = uVGA2.h wiringPi.h wiringSerial.h OBJ = test.o uVGA2.o wiringPi.o wiringSerial.o LIBS+=-lwiringPi -lpthread -lrt -lbcm2835 %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) %.o: %.S start.S vectors.S $(AS) $(ASFLAGS) $< test: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) $(LIBS) #Cleanup .PHONY: clean clean: rm -f *.o *~ core *~ Was muss ich im Makefile nun noch dazuschreiben um diese Assembler Files mit kompilieren zu können???? Bin dankbar für Tipps! lg Manfred
Seh' dir doch mal das Makefile in dem von dir verlinkten Repo an:
1 | vectors.o : vectors.s |
2 | $(ARMGNU)-as vectors.s -o vectors.o |
Deine Makefile wird allerding so nur funktionieren wenn du entweder a) Auf dem Raspberry pi kompilierst b) der GCC in $path der gcc für ARM ist Besser wäre es, in der Makefile direkt den GCC für ARM (arm-unknown-linux-gnueabi-gcc) anzugeben. Manfred Brunni schrieb: > Was muss ich im Makefile nun noch dazuschreiben um diese Assembler Files > mit kompilieren zu können???? Assembler-Quellen werden nicht kompliert, sie werden assembliert. Dazu brauchst du einen Assembler (as, bzw arm-unknown-linux-gnueabi-as) Dieser erzeugt dir eine Objektdatei, welche vom Linker mit den vom Compiler erzeugten Objektdateien zum ausführbaren BLOB verknüselt werden.
Hallo Lukas, danke für deine Antwort jedoch kann ich dir leider nicht wirklich folgen da meine Kenntnisse da leider zu gering sind. :-/ Ich programmiere momentan am PI direkt, also wird auch alles dort kompiliert. das obere Makefile funktioniert ja auch für die ganze C-Files und Header files welche ich zusätzlich verwende, aber was muss ich nun zusätzlich im makefile für die *.S Dateien eingeben damit diese dann assembliert und dem Linker übergeben werden? lg manfred
hallo joachim, ja das stimmt wahrscheinlich, hab irgendwo gelesen, dass die endung .S statt klein .s lauten muss. hab ich abgeändert, auch im makefile. lg manfred
Manfred Brunni schrieb: > $(AS) $(ASFLAGS) $< Was soll eigentlich die leere Pipe ? Kommen Fehlermeldungen ?
Nein, Fehlermeldungen werden keine angezeigt. Außer natürlich ich verwende die GET32 oder PUT32 funktion, dann regnet es undefined reference to GET32 .. was passiert da eigentlich im dem schnipsel auf dem Auszug der vectors.S: .globl GET32 GET32: ldr r0,[r0] bx lr könnte man da auch direkt im C-Code mittels inline assembler eine funktions schreiben die dann den inhalt eines bestimmten registers übergibt. verstehe irgendwie den Weg von extern unsigned int GET32 ( unsigned int ) zu der schlussendlichen GET32 Funktion nicht. wo und wie übergibt die GET32 Funktionen den Registerwert? Sorry hab keine asm Kenntnisse. lg manfred
Joachim Drechsel schrieb: > Manfred Brunni schrieb: >> $(AS) $(ASFLAGS) $< > > Was soll eigentlich die leere Pipe ? > Kommen Fehlermeldungen ? Makefiles sind keine Shellskripte. http://www.ijon.de/comp/tutorials/makefile.html#pattern >$< die erste Abhängigkeit Wenn ich die READMEs im git richtig verstanden hab, ist das baremetal-Programmierung ohne OS drunter, willst du das wirklich?
Manfred Brunni schrieb: > Sorry hab keine asm Kenntnisse. Ja - bleed. Und ich habe auf dem RPi das alles noch nicht probiert ;) Fakt ist, der Linker findet die Funktion aus irgendeinem Grund nicht. Wenn diese in einem Quellfile definiert ist sollte das klärbar sein.
BTW: ich habe hier auch ein Raspbberry pi, wenn du hier ein vollständiges Beispiel posten würdest, kann das zur Fehlersuche beitragen.
Lukas K. schrieb: > Wenn ich die READMEs im git richtig verstanden hab, ist das > baremetal-Programmierung ohne OS drunter, willst du das wirklich? was genau meinst du damit? Probleme mit Linux? Es werden ja nicht alle Timer benötigt, Timer 1 soll ja frei sein. Es wäre halt fein wenn man z.B. System Timer Compare 1 (Seite 172 im Broadcom Manual) benutzen kann damit dieser im Hintergrund unabhängig nach einem Match einen Interrupt auslöst oder einfach nur das zugehörige Flag zum Abruf bereit stellt. Zum Spielen würde es ja schon mal ausreichen wenn man in einem main Programm die GET32 und PUT32 Befehle ausführen kann um z.B. folgende Funktion vom ersten Link zu testen. if(1) { //use the counter match and the counter match flag in the counter //status register interval=0x00100000; rx=GET32(CLO); rx+=interval; PUT32(C1,rx); PUT32(CS,2); for(rb=0;rb<4;rb++) { while(1) { ra=GET32(CS); if(ra&2) break; } rx+=interval; PUT32(C1,rx); PUT32(CS,2); PUT32(GPCLR0,1<<16); //led on while(1) { ra=GET32(CS); if(ra&2) break; } rx+=interval; PUT32(C1,rx); PUT32(CS,2); PUT32(GPSET0,1<<16); //led off } } https://github.com/dwelch67/raspberrypi/blob/master/blinker07/blinker07.c Kann auch sein, das ein solches Vorhaben im Verbindung mit Linux drauf als OS sowieso zum Vergessen ist. Mir geht eben Flexibilität wie man sie bei einem standard µC ohne OS hat ein wenig ab. (Zugriff auf die ganze Peripherie etc. auf Low Level Ebene halt). Lg Manfred
Manfred Brunni schrieb: > Kann auch sein, das ein solches Vorhaben im Verbindung mit Linux drauf > als OS sowieso zum Vergessen ist. Mir geht eben Flexibilität wie man sie > bei einem standard µC ohne OS hat ein wenig ab. (Zugriff auf die ganze > Peripherie etc. auf Low Level Ebene halt). > > Lg Manfred Du hast praktisch zwei möglichkeiten deine Programme auf den Raspberry pi zum laufen zu bringen a) Beliebige Linux-Distro: Dann unterscheidet sich das Raspberry pi bis auf andere CPU, vergleichsweise geringen Performance und das Vorhandensein diverser Hardware-Einheiten nicht übermäßig von einen generischen Linux-Rechner. Mit allen üblichen Einschränkungen eines Betriebssystemns wie keinem direkten Hardware-Zugriff. b)Baremetal, also ohne Betriebssystem: Du gibst dem Bootloader statt dem Linux-Kernel dein eigenes BLOB mit auf den Weg. Vorteil: du kannst nach belieben in der Hardware rumstochern, kein Kernel und niemand hindert dich daran. Nachteil: du musst praktisch alles "von Hand zu Fuß" machen, UART, Grafikausgabe, einfach alles Ich persönlich würde von b) deutlich Abstand nehmen. Wenn meine Anwendung für den Raspberry Pi timingkritische Teile enthält, flansche ich entweder einen µC an oder schreibe, wenn mir danach ist ein Kernelmodul. Wie üblich daher die Frage: WAS willst du erreichen, nicht was für Ansätze hast du bereits unternommen.
WO liegt nun eigentlich so genau dein Problem? Ich hab mir mal das git-repo geklont, den blinker07 auf dem PC cross-compiliert (direkt aufm raspi bauen geht genauso): meinen cross-Compiler (ich war faul und hab den bereits gebauten von http://archlinuxarm.org/developers/distcc-cross-compiling genommen) in $PATH geworfen, in der Makefile das Präfix angepasst (arm-unknown-linux-gnueabi) mit make gebaut, die blinker07.bin auf die Boot-Partition der SD-Karte kopiert, in der config.txt
1 | kernel=blinker07.bin |
eingetragen, die SD-Karte eingeworfen und die LED-Blinkt wie sie es sollte.
Hallo Lukas, vielen Dank für deine Tipps. Eine direkte zeitkritische Anwendung habe ich momentan (noch) nicht, bin noch bezüglich Raspberry Pi am Anfang und möchte mich langsam herantasten was so alles möglich ist und wie weit man die Peripherie ansteuern kann. Nach deinem Posting bin ich nun aufgeklärter. Ich dachte mir, ich kann von Linux aus auf z.B. Timer Compare Register zugreifen und den Inhalt so direkt manipulieren. Ich wusste nicht, dass das die blink07 Programm statt dem Linux auf die SD Karte muss also dort gar kein Linux als OS läuft. vom µC Programmieren ist man eben gewohnt z.B. einen Background Timer zu starten der z.B. alle 100ms überläuft und in seiner ISR eine Variable hochzählt, irgendwas abfragt etc. also nicht vom eigentlichem Hauptprogramm abhängig ist (Polling) Ich habe das am PI nun so gelöst, dass ich aus der time.h timespec.tv_nsec verwende (System Timer in nano Sek.) und in einem Thread (verwende dafür die Funktion "piThreadCreate" aus "wiringPi.h") der parallel zum Hauptprogramm abläuft, abfrage ob bereits 100ms vergangen sind. somit habe ich einen einergermaßen brauchbaren 100ms takt. Ist zwar kein direkter Interrupt aber was anderes als Threads zu erzeugen (also quasi Polling) welche die Multitaskingfähigkeit von einem OS ausnützt, bleibt ja nicht übrig oder, aber gut mit 700MHz Systemtakt geht das ja schon recht flott :-) Lg Manfred
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.