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