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
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?
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.
_\|/_ 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?
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.
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.
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
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
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
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
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ß.
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
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
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)"
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 :)
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.
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.
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.
> 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
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.
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
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.
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