Forum: Compiler & IDEs Probleme beim bauen eines GCC Cross Compiler (MIPS)


von Dimi S. (ilovespeccy)


Lesenswert?

Hallo,
endlich mal habe ich wieder Zeit dafür und beschäftige mich mit einem 
MIPS-1 SoftCore "Plasma". Ein Testdesign auf einem Altera DE1 Board 
läuft bereits. Besteht aus:

* CPU
* 8Mb SDRAM
* 2 Timer
* UART
* SD-Card (SPI)
* Tasten/Schalter/LEDS

CPU ist mit 12.85MHz getaktet, SDRAM mit 90MHz, ohne Cache
Alles klappt soweit.
Bis jetzt habe ich GCC (gebaut von Steve Rhoads) benutzt. Es ist aber 
reinen C-Compiler, ohne libc u.s.w.
Ich habe mich entschieden einen GCC (MinGW) mit Newlib selber zu bauen 
und habe es geschafft!

* Binutils 2.22
* GCC 4.6.2 (C,C++)
* Newlib 1.20
* GDB 7.4

Es klappt sogar :)
Nur mit PRINTF habe ich Probleme. Ich weiss nicht warum. Direkte 
WRITE-Aufruf geht aber.

Hier ist mein Start-up code:
1
   .text
2
   .align 2
3
   .global _start
4
   .ent    _start
5
6
_start:
7
   .set noreorder
8
9
   la    $gp, _gp             #initialize global pointer
10
   la    $5, __bss_start      #$5 = .sbss_start
11
   la    $4, _end             #$2 = .bss_end
12
   la    $sp, 0x7FFFF         #initialize stack pointer
13
14
$BSS_CLEAR:
15
   sw    $0, 0($5)
16
   slt   $3, $5, $4
17
   bnez  $3, $BSS_CLEAR
18
   addiu $5, $5, 4
19
20
21
   jal main
22
   nop
23
24
loop:
25
   j loop
26
   .set reorder
27
   .end _start

LD-Script:
1
ENTRY(_start)
2
3
SECTIONS
4
{
5
   . = 0x00000000;
6
   .text :
7
   {
8
      boot.o (.text)
9
      *(.text)
10
   }
11
   .data : { *(.data) }
12
13
   _gp = . + 0x7ff0;
14
   __bss_start = .;
15
16
   .bss : { *(.bss) }
17
18
   _end = .;
19
}

Syscalls:
1
#include <sys/stat.h>
2
3
#define _MR(A) (*(volatile unsigned int*)(A))
4
#define _MW(A,V) *(volatile unsigned int*)(A)=(V)
5
6
int fstat(int file, struct stat *st)
7
{
8
   st->st_mode = S_IFCHR;
9
   return 0;
10
}
11
12
int read(int file, char *ptr, int len)
13
{
14
   return 0;
15
}
16
17
int lseek(int file, int ptr, int dir)
18
{
19
   return 0;
20
}
21
22
int isatty(int file)
23
{
24
   return 1;
25
}
26
27
int close(int file)
28
{
29
   return -1;
30
}
31
32
int write(int file, char *ptr, int len)
33
{
34
   int todo;
35
   for (todo = 0; todo < len; todo++)
36
   {
37
      while(_MR(0x80000030)); // UART busy???
38
      _MW(0x80000020, *ptr++); // write to UART
39
   }
40
   return len;
41
}
42
43
caddr_t sbrk(int incr)
44
{
45
   extern char _end; /* Defined by the linker */
46
   static char *heap_end;
47
   char *prev_heap_end;
48
   if (heap_end == 0)
49
   {
50
      heap_end = &_end;
51
   }
52
   prev_heap_end = heap_end;
53
   heap_end += incr;
54
   return (caddr_t) prev_heap_end;
55
}

Programm:
1
#include <stdio.h>
2
3
char fff[3] = {'a','b','c'};
4
5
int main(void)
6
{
7
   write(NULL,fff,3);
8
   printf("Hallo\n");
9
   while(1);
10
}

Ich komme leider nicht mehr weiter. Ich vermute, es liegt am heap/stack.
Da ich bis jetzt nur fertige Compiler (mit fertige crt0.o und 
LD-Scripts) verwendet habe, habe ich wenig Erfahrung mit Compilerbau.

Ich hoffe mir kann jemand helfen.

MfG aus Westerwald
Dimi

von _\|/_ (Gast)


Lesenswert?

Wo liegen deine initialisierten Daten? Müssen die erst aus dem Flash 
o.ä. in den RAM geladen werden oder werden die schon von einem 
Bootloader dahin kopiert?

von Dimi S. (ilovespeccy)


Lesenswert?

Das Programm und die Daten werden über USB ins SDRAM geladen ab Adresse 
0x00000000.
Dann wird CPU Resettet.

von _\|/_ (Gast)


Lesenswert?

Ich hatte ganz ähnliche Probleme aber auf einem Board mit ARM-Prozessor. 
Das printf() holt sich Speicher. Ich würde mal vermuten, das es etwas 
mit dem Heap und/oder Stack zu tun hat. Eventuell kollidiert der Heap 
mit dem Stack.

von Dimi S. (ilovespeccy)


Lesenswert?

_\|/_ schrieb:
> Ich hatte ganz ähnliche Probleme aber auf einem Board mit ARM-Prozessor.
> Das printf() holt sich Speicher. Ich würde mal vermuten, das es etwas
> mit dem Heap und/oder Stack zu tun hat. Eventuell kollidiert der Heap
> mit dem Stack.

Ich habe genug RAM, deswegen habe ich schon probiert Stack auf Adresse 
0x0013ffff zu legen (1Mb). Gleiches Problem.
Ich versuche mit malloc und Unterprogrammen zu spielen und die Adressen 
beobachten. Vielleicht fällt mir was auf.

Haben Sie Ihr Problem mit printf gelöst?

von _\|/_ (Gast)


Lesenswert?

Hier im Forum ist ein "du" in Ordnung. ;-)

Ich hatte mehrmals ganz ähnliche Probleme. Die normale Ausgabe über z.B. 
UART funktionierte aber alles andere nicht. Bei mir hatte es immer etwas 
mit dem Stack, Heap oder Speicher zu tun. Also entweder war die section 
data nicht richtig initialisiert oder der Heap hat den Stack 
überschrieben oder der SDRAM war allgemein nicht richtig initialisiert. 
Die SDRAM Chips brauchen ja eine genau festgelegte 
Initialisierungsprozedur. Aber das macht hoffentlich der Loader bei dir, 
wenn du die Daten über USB lädst.

von mete (Gast)


Lesenswert?

la    $sp, 0x7FFFF         #initialize stack pointer

Sollte der Stack nicht auf 4-byte aligned sein? Wenn die CPU das 
naechste Word auf den Stack schreiben will, verwendet er die Adresse 
0x7FFFB, das ist dezimal 524283, und somit nicht durch 4 teilbar. 
Moeglicherweise bekommst du deswegen einen Speicherzugriffsfehler.

von Dimi S. (ilovespeccy)


Lesenswert?

Habe alles was ich konnte ausprobiert, klappt trotzdem nicht.
Wie es aussieht, verwenden kompilierte Programme MIPS-Instruktionen, die 
von "Plasma" nicht unterstützt werden.

Im Beschreibung zum "Ion" (opencores) steht folgendes:
1
Note that none of the samples use the standard libc included with the
2
toolchain -- the samples use no explicit library functions or *intrinsic*
3
gcc functions such as printf. All supporting i/o functions (including the 
4
version of printf actually used) are homebrew, scavenged from the net and 
5
bundled into an ad-hoc support library.
6
This is because gcc insists in using some MIPS32 instructions even with the 
7
-mips1 flag; specially when using soft floating point support (-msoft-
8
float). Until I write a trap handler for those MIPS32 opcodes, or I figure 
9
out how to get rid of them, I can't use the standard library. I will 
10
probably have to recompile newlib (a libc replacement for embedded systems) 
11
for a R3K target that as far as I know is not supported, so it may take some 
12
time to sort this out.

Also, geht nicht. Schade.
Vielleicht kann mir jemand etwas empfehlen.
Habe keine Lust libc neu zu schreiben.

MfG

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dimi S. schrieb:

> Wie es aussieht, verwenden kompilierte Programme MIPS-Instruktionen, die
> von "Plasma" nicht unterstützt werden.
>
> Im Beschreibung zum "Ion" (opencores) steht folgendes:
  
1
All supporting i/o functions [...] are homebrew, [...]
2
because gcc insists in using some MIPS32 instructions even
3
with the -mips1 flag; [...]

Wenn GCC passenden Code erzeugt, und sich das Problem auf Bibliotheken 
beschränkt, liegt esnicht am Compiler.

Ein Grund kann zum Beispiel sein, daß die verwendete C-Bibliothek nicht 
die Multilib-Optionen bzw. -Konfiguration unterstützt, die GCC 
voraussetzt.

Lösung ist in dem Falle, die Bibliothek korrekt zu generieren; entweder 
mit Mulilib-Layout passend zum GCC, oder ohne Multilibfähigkeit und so 
configured, daß das Zeug zur verwendeten Architektur passt.

> Vielleicht kann mir jemand etwas empfehlen.

Gute Anlaufstelle bei solchen Fragen ist Anmeldung bei der GCC 
Mailingliste gcc-help@ siehe http://gcc.gnu.org/lists.html

von Dose (Gast)


Lesenswert?

bitte sende mir mal die ausführbahre Datei.

Ich will mir mal mit objdump -D den erzeugten ASM-code auschauen.




René

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Ich nutzt auch einen anderen GCC.

Kannst du das Crosskompilieren vom GCC mal dokumentieren?

Ich bin mal bei einem Versuch für den ARM gescheitert.

Zu deinem Code. Da du eine andere Toolchain benutzt, kann es sein du 
hast eine andere ABI.
Die ABI definiert die Parameterübergabe der Funktionen.

Ich habe eine Idee was es sein kann. Das Register $25 wird von Start up 
Code nicht initialisiert. Ich hatte ein ähnliches Problem mit dem Plasma 
und habe im Simulator herausgefunden, das er immer was vom Register 25 
wollte. Da habe ich mal im Netz gesucht und hatte auch was dazu 
gefunden. Ich glaube die Rücksprungaddresse wird aus dem Register 25 
berechnet.
Füge mal die eine Zeile ein.

$BSS_CLEAR:
   sw    $0, 0($5)
   slt   $3, $5, $4
   bnez  $3, $BSS_CLEAR
   addiu $5, $5, 4


   la    $25, main  #set register


   jal   main
   nop

von Dose (Gast)


Lesenswert?

Ich hatte noch eine bessere Textstelle.


Das ist genau das was ich meinete.
Die Sprungadressen holt er aus der global offset table. Und für die 
Berechnung ist $t9 wichtig.



http://www.linux-mips.org/wiki/PIC_code

von Dimi (Gast)


Lesenswert?

Danke René,

ich probiere's mal aus!

MfG

p.S. Es wäre super, wenn Plasma (oder andere MIPS-SoftCore) 
FPU-Coprocessor unterstützen würde. Mit -msoft-float muss -libgcc auch 
verwendet werden. Das macht ein kleines Programm (nur ein printf) direkt 
40kb groß.

von Dimi (Gast)


Lesenswert?

Dose schrieb:
> bitte sende mir mal die ausführbahre Datei.

René D. schrieb:
> Kannst du das Crosskompilieren vom GCC mal dokumentieren?

Mache ich!

von Dimi S. (Gast)


Lesenswert?

Ich komme nicht weiter...

ich habe versucht mein Programm mit Plasma-Emulator zu debuggen 
(mlite.exe) und es hängt schon ganz am Anfang.
Und zwar hier:
1
$BSS_CLEAR:
2
   sw    $0, 0($5)
3
   slt   $3, $5, $4
4
   bnez  $3, $BSS_CLEAR
5
   addiu $5, $5, 4
addiu wird nie ausgeführt und es hängt hier.
So wie ich verstanden habe, wird nach "branch"-Instruction die nächste 
Zeile noch ausgeführt und erst dann springt "pc" nach "BSS_CLEAR". Bei 
simulation ist es aber nicht so.

@René
Wie silumierst du deine MIPS-Code? Gibt's Alternative zu mlite?

MfG

von Dimi S. (Gast)


Lesenswert?

... hat sich erledigt!
habe ".set noreorder" vergessen :)

von Dimi S. (Gast)


Angehängte Dateien:

Lesenswert?

@René,
hier ist mein Programm.
"write" klappt, "puts" nicht.
Gebaut mit Sourcery CodeBench Lite Edition for MIPS ELF
https://sourcery.mentor.com/sgpp/lite/mips/portal/subscription3537?lite=MIPS

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

> @René
> Wie silumierst du deine MIPS-Code? Gibt's Alternative zu mlite?


Ich simuliere den VHDL code mit GHDL und schaue mir die Signal in 
gtkwave an.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

ich muss gerade am Sprungbefehl was richten.
Wenn ich das habe, probiere ich mal deinen Code in der Mais-CPU.

von Dimi S. (ilovespeccy)


Lesenswert?

Mein Problem ist zum Teil gelöst! (endlich mal)
Es lag an meinem ld-script. Jetz klappt das größte Teil von libc.
printf geht auch, aber nur ohne Parameter.
Bei der Untersuchung von kompilierten Test-Programmen habe
ich festgestellt, dass libgcc (printf benötigt diese lib weil FPU fehlt)
trotz -mips1 Anweisung benutzt Opcodes von MIPS32, in meinem fall "CLZ".
Ab da geht alles natürlich durcheinander.

Jetzt ist die frage, wie kann man GCC mitteilen, das solche Befehle
nicht benutzt werden???

Ich habe mir die Quelltexte von GCC angeschut. WAHNSINN! Ich blicke da
einfach nicht durch :)

Vielleicht hat jemand einen Tipp für mich?

MfG aus Westerwald

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dimi S. schrieb:

> Jetzt ist die frage, wie kann man GCC mitteilen, das solche Befehle
> nicht benutzt werden???
>
> Ich habe mir die Quelltexte von GCC angeschut. WAHNSINN! Ich blicke da
> einfach nicht durch :)
>
> Vielleicht hat jemand einen Tipp für mich?

Was hat denn die Nachfrage bei den GCC-Experten ergeben, wie bereits 
hier empfohlen?

Beitrag "Re: Probleme beim bauen eines GCC Cross Compiler (MIPS)"

von Dimi S. (ilovespeccy)


Lesenswert?

Ich wohne seit 11 Jahren in Deutschland und habe mich mehr mit Deutsche
Sprache befasst. Mein Englisch ist gaaaaanz schlecht. Ich kann zwar
Dokus/Datasheets lesen, aber kann nicht Englisch schreiben. Ich habe nie
Englisch gelernt, nur seit 15 Jahren benutze ich englische Windows- und
Linux- versionen. Und wenn ich was nicht verstehen kann, mir hilft
"translate.google.de"

Ich werde aber versuchen bei "GCC mailing lists" klar zu kommen!

p.S. Ich habe mir vor 3-4 Jahren einen Englisch-Kurs auf CD's besorgt,
kamm aber noch nicht richtig dazu. Habe leider nicht viel Freizeit
wie wir alle :)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Als Topic sowas:

"mips-gcc uses unsupported MIPS32 instruction with -mips1"

Auf jeden Fall wird hilfreich sein

- ein kleine Progamm (möglichst ohne #include") das zu dem Problem 
führt. Wenn die Instruktion CLZ ist lässt es sich vielleicht schon durch 
Verwendung von __builtin_clz() nachstellen; evtl auch eine einfache 
float/double-Operation, die entsprechenden libgcc-Code brauch.

- Auf jeden Fall die Ausgabe des Compiler mit -v also:

$ mips-gcc -v -mipsl programm.c [optionen]

Das werden einige unhübsche Zeilen, die aber darüber Auskunft geben, wie 
der Compiler erzeugt wurde, welche Multilib er verwendet, welche 
Version, etc.

Du kannst den Text auch auf Deutsch hier schreiben und ich übersetze es 
dann.

von Dimi S. (Gast)


Lesenswert?

Jetzt klappt es so wie es sein soll!!!

Ich habe aber einen anderen Weg gegangen...
statt GCC habe ich an der Plasma-Core was geändert.
Im Plasma-Simulator "mlite.c" habe ich 2 opcodes hinzugefügt:
* clz - anzahl führendn Nullen
* mul - untere 32 bit des produktes von rt und rs ins rd ablegen
Jetzt geht es!!!

aber...

Steve Rhoads hat geschrieben, das wegen irgendwelchen Patenten sind 
einige
Opcodes im Plasma nicht implementiert. Was macht man in so einem Fall???
Klar, für meine Hobbyprojekte kann ich es benutzen, aber was macht z.B
der René?? Wenn diese Opcodes im Mais-SoftCore implementiert werden dann
hat man eine vollständige Toolchain mit allem was man braucht: libc, 
libm,
libgcc u.s.w.

Kann man im Quelltext diese kommentiert lassen und wer braucht, einfach
auskommentieren??? Oder werden damit auch die Rechte verletzt?

Wenn das nicht geht, dann bleibt nur GCC zu patchen, was ich als keine
schöne Lösung finde.

MfG aus Westerwald

p.S. ich wollte noch GCC mit C++ für MIPS bauen und ausprobieren.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Dimi S. schrieb:
> Jetzt klappt es so wie es sein soll!!!
>
> Ich habe aber einen anderen Weg gegangen...
> statt GCC habe ich an der Plasma-Core was geändert.
> Im Plasma-Simulator "mlite.c" habe ich 2 opcodes hinzugefügt:
> * clz - anzahl führendn Nullen
> * mul - untere 32 bit des produktes von rt und rs ins rd ablegen
> Jetzt geht es!!!
>
> aber...
>
> Steve Rhoads hat geschrieben, das wegen irgendwelchen Patenten sind
> einige
> Opcodes im Plasma nicht implementiert. Was macht man in so einem Fall???
> Klar, für meine Hobbyprojekte kann ich es benutzen, aber was macht z.B
> der René?? Wenn diese Opcodes im Mais-SoftCore implementiert werden dann
> hat man eine vollständige Toolchain mit allem was man braucht: libc,
> libm,
> libgcc u.s.w.
>

clz habe ich nicht in meinem opcode

Den Befehl habe ich auch nicht in dem Dokument mips-isa.pdf gefunden.
http://www.google.de/url?sa=t&rct=j&q=mips-isa.pdf&source=web&cd=1&ved=0CGMQFjAA&url=http%3A%2F%2Fwww.weblearn.hs-bremen.de%2Frisse%2FRST%2Fdocs%2FMIPS%2Fmips-isa.pdf&ei=GLiuT4K6DITbtAahtfSxBg&usg=AFQjCNG_oDav4sLHkdo1G54PtGWyxUP38w&cad=rja

Bei C bin ich nur Ansatzweise unterwegs. Bin noch im Assembler um Fehler 
im Softcore zu finden.

Na klar will ich auch auf die höheren Sprache kommen. Deshalb ist die 
Info von dir sehr interessant.
Compilerbau ist auch Neuland für mich.

Die von Steve Rhoads erwähnten MIPS Patente sollten bereits ausgelaufen 
sein.
[The patent for the unaligned memory access instructions expired Dec 23, 
2006.]

Ich habe vor kurzem gelesen, das eine Chinesische Firma trotzdem eine 
Lizenz bei MIPS erworben hat. Das habe ich auch nicht verstanden.
Das passt vom Sinn nicht zusammen. Oder das war ein anderes Patent.

von Dimi S. (ilovespeccy)


Lesenswert?

> Den Befehl habe ich auch nicht in dem Dokument mips-isa.pdf gefunden.

Dieser Befehl gehört zu MIPS32 Instruction Set:
http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01.pdf

> Ich habe vor kurzem gelesen, das eine Chinesische Firma trotzdem eine
> Lizenz bei MIPS erworben hat. Das habe ich auch nicht verstanden.
> Das passt vom Sinn nicht zusammen. Oder das war ein anderes Patent.

Ich habe das auch vor kurzem gelesen.
Es gibt aber z.B. "Amber" und "Storm" Cores, die ARM-kompatibel sind.
ARM ist auch wie MIPS eine "kommerzilelle" Architektur.
Vielleicht braucht man diese Patente nur für Endgeräte?

MfG

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Dimi S. schrieb:
>> Den Befehl habe ich auch nicht in dem Dokument mips-isa.pdf gefunden.
>
> Dieser Befehl gehört zu MIPS32 Instruction Set:
> http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01.pdf


Ich habe den Befehl auch in
MIPS32TM Architecture For Programmers Volume II: The MIPS32TM 
Instruction Set
gefunden.
Da gibt es ein Feld zu welcher Architektur es gehört. Alle Befehle sind 
MIPS32(MIPS I) oder ähnlich gekennzeichnet.

Gerade beim clz steht nur MIPS32. Hier würde mich schon interessieren wo 
der Befehl hingehört. Doch wenn der GCC den Befehl benutzt, dann auch 
wieder...
Ich wüsste gar nicht was ich mit den führenden Nullen anfange sollte.

von Dose (Gast)


Lesenswert?

Nur zur Info,

ob neu oder alt mal sehen was aus MIPS wird.


http://www.heise.de/ct/meldung/Spekulationen-um-MIPS-Verkauf-1541100.html

von Dose (Gast)


Lesenswert?

René D. schrieb:
> Die von Steve Rhoads erwähnten MIPS Patente sollten bereits ausgelaufen
> sein.
> [The patent for the unaligned memory access instructions expired Dec 23,
> 2006.]


Ich habe das Mips Patent gefunden.

http://www.google.com/patents/US4814976

von Dimi S. (Gast)


Lesenswert?

Ich werde versuchen den "Plasma"-Core mit MIPS32-Befehlen zu erweitern.
Es ist die sauberste Lösung.

p.S. ich schreibe gerade meinen eigenen MIPS32-Emulator (C++ Builder)
um alles testen zu können.

von Dose (Gast)


Lesenswert?

Dimi S. schrieb:
> p.S. ich schreibe gerade meinen eigenen MIPS32-Emulator (C++ Builder)
> um alles testen zu können.



Da gibt es doch auch schon genügend Simulatoren.

http://pages.cs.wisc.edu/~larus/spim.html
auch mit QT Oberfläche

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.