Forum: Compiler & IDEs GCC/newlib für M16C/62P: Keine Funktionsaufrufe möglich?


von kpeter (Gast)


Lesenswert?

Hallo zusammen

Ich habe hier ein Board mit einem Mikrocontroller vom Typ Renesas 
M16C/62P vor mir liegen. Das Flashen des Programms funktioniert 
einwandfrei.

Mein Problem liegt allerdings darin, dass ich aus meiner main()-Funktion 
keine andere Funktionen aufrufen kann, zumindest wird nicht korrekt in 
die aufrufende Funktion zurückgesprungen.

Hier mein Minimalbespiel:
1
void test() {
2
    unsigned int i=10000;
3
    while(--i > 0) {}
4
}
5
6
int main() {
7
    unsigned int i = 0;
8
9
    PD6_4 = 1; // LED0
10
    PD8_7 = 1; // LED1
11
12
    P6_4 = 1;
13
    P8_7 = 1;
14
    
15
    test();
16
17
    while (1) {
18
        while (i++<9500) {}
19
        test(); // -> LED leuchtet dauerhaft (P8_7=0 wird nicht erreicht)
20
        P8_7=1;
21
        while (i++<10000) {}
22
        P8_7=0;
23
        i=0;
24
    }
25
26
    return 0;
27
}
Lösche ich die markierte Zeile, funktioniert das Programm einwandfrei.

Zur Kompilierung verwende ich folgenden Befehl:
1
m32c-elf-gcc -Wall -mcpu=m16c -o ledtest.elf main.c

Hat jemand eine Idee woran das liegen könnte?

Vielen Dank für eure Hilfe.

Grüsse
Peter

von (prx) A. K. (prx)


Lesenswert?

Wie wird in dieser Umgebung der Stack definiert? Wenn der im Wald steht, 
dann wäre so ein Verhalten gut möglich.

von kpeter (Gast)


Lesenswert?

Mein GCC habe ich mit newlib* (welche ihrerseits libgloss einschliesst) 
kompiliert. Somit müsste der Stack durch libgloss gesteuert werden. Ich 
habe aber diesbezüglich fast keine Erfahrung. Wie kann ich das 
herausfinden?

Wenn eine andere Konfiguration einfacher zum Ziel führen würde, kann ich 
auch gerne umstellen.

* http://sourceware.org/newlib/

von isio (Gast)


Lesenswert?

Für den Code brauchst Du weder eine newlib noch eine libgloss.

Es wäre interessanter, Du würdest Deinen Startup-Code und
Dein Linker-Command File zeigen...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Von der libgloss wird doch zumindest crt0.S verwendet, oder nicht?

Die Frage ist, ob newlib / libgloss richtig generiert wurden und zum 
Compiler und dessen multilib layout passen.

Ein Problem mit dem Code sind zudem die unsinnigen Warteschleifen, die 
komplett wegoptimiert werden können.  Damit wird die LED sehr schnell 
zwischen an / aus hin- und hergeschaltet und es sieht so aus, als würde 
sie immer brennen.

von Olaf (Gast)


Angehängte Dateien:

Lesenswert?

> Hat jemand eine Idee woran das liegen könnte?

Ich hab mal eine Gegenfrage. Wie kann eigentlich irgendjemand auf die 
Idee kommen Programme in C fuer eine Microcontroller zu schreiben ohne 
das man sich mit Linkerscript und Startupcode beschaeftigt?
Ich meine man muss die doch fuer jedes seiner Projekte anpassen. Es gibt 
ja gerade auch die M16C mit unterschiedlichen Ram/Flash. Und selbst fuer 
denselben Controller koennen die unterschiedlichens Werte notwendig 
sein. (z.B Bootloader ja/nein)

Du brauchst also ein Linkerscript das den Speicherausbau deines 
Prozessors beschreibt und ein Startupcode der damit etwas anfangen kann.

Zur Inspiration mal die beiden Dateien aus einem meiner Projekte. Du 
musst sie aber anpassen!

Olaf

p.s: Aber schoen zu sehen das noch einer den 62P nutzt. :-)

von (prx) A. K. (prx)


Lesenswert?

@Olaf:

Ist das nicht ein etwas hinterfotziger Weg, R0L mit 0 zu laden?
   mov.b #%hi8(__bssstart),r0l

Und bei "set user stack pointer" wird nicht der USP sondern der der ISP 
gesetzt (U=0 ab Reset). Womit sich auch der nächste Kommentar erledigt.

von Olaf (Gast)


Lesenswert?

> Ist das nicht ein etwas hinterfotziger Weg, R0L mit 0 zu laden?

Kann ich dir jetzt auch nicht sagen. Ich hab das auch nur uebernommen 
und etwas angepasst und die M16C nie in Assembler programmiert.

Olaf

von (prx) A. K. (prx)


Lesenswert?

Das war eine rhetorische Frage. BSS liegt stets im RAM und das liegt bei 
den M16C stets in den ersten 64KB. R0 wiederum enthält bei SSTR keine 
Adresse, sondern die zuschreibenden Daten. Korrekt wäre es also, R0L 
direkt mit 0 zu laden, statt mit einem Adressteil, der stets 0 ist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Den Adressteil zu verwenden ist aber erklärender als eine magische 
Konstante wie "0".  Ok, selbst in Assembler gibt es auch Kommentare 
dafür :-)

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:
> Den Adressteil zu verwenden ist aber erklärender als eine magische
> Konstante wie "0".

Andersrum. R0 enthält den zu schreibenden Wert, nicht den oberen Teil 
einer Adresse. Den Adressteil zu verwenden ist also gerade der falsche 
Weg und die Konstante 0 der richtige. Immerhin handelt es sich um jenes 
Codefragment, das BSS auf 0 setzen soll. Die "magische" 0.

Was oben steht entspricht in C formuliert ungefähr
1
  memset(lo16(__bssstart), hi8(__bssstart), __bsssize);
statt
1
  memset(__bssstart, 0, __bsssize);
und das funktioniert nur deshalb, weil hi8(__bssstart) immer 0 ist. hi8 
sind die Bits 16..23 (hoffentlich, sonst ...).

Korrekt wäre also
1
;; Loeschen der Variablen
2
          mov.b #0,r0l
3
          mov.w #__bssstart,a1
4
          mov.w #__bsssize, R3
5
          sstr.b

von kpeter (Gast)


Lesenswert?

Besten Dank für eure zahlreichen Beiträge!
Ich werde mir Olaf's Linker-Script mal zu Gemüte führen. Allerdings muss 
ich mich hier noch komplett in die Materie einlesen, da mir diese Arbeit 
bisher abgenommen worden ist.

Mittlerweile funktioniert der Stack jedoch (bis jetzt zumindest) 
einwandfrei. Momentan versuche ich noch herauszufinden welche magische 
Änderung dies bewirkt hat (hatte mit zahlreichen Startup-Codes, 
Linker-Scripts und Compiler-Flags experimentiert).

Sobald neue Fragen auftauchen, melde ich mich gerne wieder.

Schöne Weihnachten und erholsame Feiertage,
Peter

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.