Forum: Compiler & IDEs M16C GCC Minimalbeispiel


von Florian P. (florianpose)


Lesenswert?

Hallo zusammen!

Ich fange gerade ein Projekt mit dem M16C von Renesas an und möchte 
gerne so bald wie möglich von der HEW-Entwicklungsumgebung nach GCC 
unter Linux umsteigen. Deshalb habe ich mir schon Binutils/GCC/Newlib 
für das "m32c-elf"-Target gebaut.
Ich verzweifele aber im Moment an einem minimalen Programm, dass ein 
paar LEDs zum Blinken bringen soll. Der Code und das ausgespuckte 
.mot-File sehen soweit gut aus, auch der Reset-Vektor wird geschrieben.

Es folgen das C-Programm und das Makefile. Vielleicht kann mir jemand 
von euch den entscheidenden Tipp geben:

main.c:
--------------------------
#define pd7 (*((unsigned char *) 0x03EF)) // port P7 direction register
#define p7  (*((unsigned char *) 0x03ED)) // port P7 register

void start(void);
typedef void (*ifunc)(void) __attribute__((mode(SI)));
const ifunc __attribute__((section(".resetvec"))) reset_vector = start;

void start(void)
{
    int i;

    pd7 = 0xFF; // set direction to output

    while (1) {
        p7 = 0x00; // leds off
        i = 1000;
        while (--i); // wait

        p7 = 0xFF; // leds on
        i = 1000;
        while (--i); // wait
    }
}
--------------------------

Makefile:
--------------------------
CC = m32c-elf-gcc
AS = m32c-elf-gcc
OBJCOPY = m32c-elf-objcopy

CFLAGS = -mcpu=m16c
LDFLAGS = -mcpu=m16c -nostartfiles
ASFLAGS = --m16c

all: mini.mot

mini.mot: mini.elf
  $(OBJCOPY) -O srec $< $@

mini.elf: main.o
  $(CC) $(LDFLAGS) $^ -o $@

clean:
  rm -f *.o *.elf *.mot

flash: mini.mot
  m16c-flash /dev/ttyS0 M16C mini.mot 0:0:0:0:0:0:0
--------------------------

Die Ausgaben beim Kompilieren/Flashen sehen vielversprechend aus:
$ make flash
m32c-elf-gcc -mcpu=m16c   -c -o main.o main.c
m32c-elf-gcc -mcpu=m16c -nostartfiles main.o -o mini.elf
m32c-elf-objcopy -O srec mini.elf mini.mot
m16c-flash /dev/ttyS0 M16C mini.mot 0:0:0:0:0:0:0
M16C-Flash Programmer Version 0.1

Looking for M16C/R8C...
Confirming...board replied with clock confirm of B0.
Statusregister: 80, 60

Reading boot ROM version info... VER.4.04
Sending ID data  0: 0: 0: 0: 0: 0: 0...OK.
ID verified, additional commands may now be issued.
Erasing block at  FC000...OK.
Erasing block at  FA000...OK.
Erasing block at  F8000...OK.
Erasing block at  F0000...OK.
Erasing block at  E0000...OK.
Erasing block at  D0000...OK.
Erasing block at  C0000...OK.
Writing page  C0000...OK.
Writing page  FFF00...OK.
finished.

...aber irgendwie tut sich nichts an den LEDs. Es sieht eher so aus, als 
ob die entsprechenden Pins noch immer Eingänge sind...

Ich verwende übrigens binutils 2.17 und GCC 4.1.1.

Viele Dank,
Florian

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Ich kenne den Compiler, bzw. den Startup-Code für dieses Target, zwar 
nicht, aber fehlt Dir nicht die "main"?

von Florian P. (florianpose)


Lesenswert?

Die main() heisst bei mir start() und wird über den Reset-Vektor als 
Einsprungspunkt nach einem Reset eingetragen. Ist die Namensgebung ein 
Problem? Ich hatte diese eigentlich nur gewählt, weil gcc für main() 
standardmäßig einen Rückgabewert erwartet (der hier ja keinen Sinn 
ergibt) und das Linker-Script sowieso ein _start-Symbol erwartet...

von Dirk (Gast)


Lesenswert?

Hi,

>Deshalb habe ich mir schon Binutils/GCC/Newlib für das "m32c-elf"-Target
>gebaut.

würdest du deine Binutils/GCC/Newlib veroeffentlichen? Ganz ehrlich 
gesagt sagt mir die HEW-Entwicklungsumgebung auch nicht zu und wuerde 
gerne den GCC dafuer benutzen.


Gruß,
Dirk

von Joe D. (kosmonaut_pirx)


Lesenswert?

hallo,
kenne die mcu zwar auch nicht, aber indem du deine start direkt in den 
reset packst, geht dir imho die ganze initialisierung verloren 
(stackpointer, register etc.). das kann nicht gut sein. deshalb gcc 
selber den reset vector eintragen lassen, und eine main verwenden. wie 
das bei der mcu geht, weiß ich nicht, aus eingangs beschriebenen 
gründen.
bye kosmo

von Florian P. (florianpose)


Angehängte Dateien:

Lesenswert?

Dirk wrote:
> würdest du deine Binutils/GCC/Newlib veroeffentlichen? Ganz ehrlich
> gesagt sagt mir die HEW-Entwicklungsumgebung auch nicht zu und wuerde
> gerne den GCC dafuer benutzen.

Ich habe mich grob an die folgende Anleitung gehalten:
http://www.fischl.de/thomas/elektronik/r8c/r8c_gcc.html

Allerdings sind die "--program-prefix"-Zeilen unnötig und ich musste 
wegen eines Bugs, der zum Abbruch der Kompilation der libc führte, das 
GCC-Makefile patchen (hängt an).

Alles andere war eigentlich relativ unproblematisch. Nur, dass ich noch 
kein Programm zum Laufen bekommen habe... ;-)

von mike (Gast)


Lesenswert?

Hallo Florian,

tut sich gar nichts oder glimmt die LED nur so vor sich hin? Ich kenne 
Deine Taktfrequenz nicht, aber die Zeitschleife von 1000 dürfte eine 
Blinkfrequenz von einigen kHz erzeugen, das Blinken wäre also nur mit 
einem Oszilloskop sichtbar.

Gruss

Mike

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Florian Pose wrote:

> Ist die Namensgebung ein
> Problem?

Für C ist main() essenziell.

> Ich hatte diese eigentlich nur gewählt, weil gcc für main()
> standardmäßig einen Rückgabewert erwartet (der hier ja keinen Sinn
> ergibt)

Ja, und?  Das ist halt der C-Standard.  Das ist doch nur eine
syntaktische Forderung, die kannst du leicht mit
1
int
2
main(void)
3
{
4
   // Initialisierung hier..
5
   for (;;) {
6
     // Code hier
7
   }
8
   return 0;
9
}
erfüllen.  Der Optimizer wird dann feststellen, dass die
Endlosschleife nicht verlassen werden kann, und wird das
"return 0;" letztlich ignorieren.

Die Forderung nach einem int als Returntyp besteht übrigens
nur, wenn man ein "hosted environment" hat, in einem "freestanding
environment" (-ffreestanding) besteht sie nicht.  Allerdings
verbietet man damit dem Compiler auch, allerlei Annahmen über die
Funktionen der Standardbibliothek und damit mögliche Optimierungen
zu machen.  Da zeigt sich das Dilemma, dass eben embedded applications
heutzutage keineswegs nur rein als "freestanding environment"
betrachtet werden können/sollten, da die Compiler zumindest einen
Subset der C-Standard-Bibliothek anbieten, der auch im Sinne des
Standards (und damit im Sinne eines hosted environments) genutzt
werden soll.

Damit ist das Anbringen des sinnlosen returns nach der Endlosschleife
meist der sinnvollste Kompromiss.

> und das Linker-Script sowieso ein _start-Symbol erwartet...

Das sollte aber die Bibliothek (bzw. das Laufzeitsystem aus dieser)
liefern.

von Florian P. (florianpose)


Lesenswert?

Jörg Wunsch wrote:
> Für C ist main() essenziell.

Ok, ich habe die Funktion wieder nach main() umbenannt.

>> und das Linker-Script sowieso ein _start-Symbol erwartet...
>
> Das sollte aber die Bibliothek (bzw. das Laufzeitsystem aus dieser)
> liefern.

Tut es auch, wenn ich das -nostartupfiles Flag für den Linker entferne. 
Mein Problem ist nur, dass der vom gcc erzeugte Startup-Code erstens 
riesig groß ist (.mot-File > 26K, was ich aber verschmerzen könnte), und 
zweitens, ein _start-Einsprungspunkt zwar erzeugt wird, aber dieser 
nicht in den Reset-Vektor eingetragen wird. Dem kann ich mit Einfügen 
von folgendem Code Abhilfe schaffen:
1
void start(void);
2
typedef void (*ifunc)(void) __attribute__((mode(SI)));
3
const ifunc __attribute__((section(".resetvec"))) reset_vector = start;

Allerdings läuft das Programm dann nicht richtig (die LEDS blinken zwar, 
aber völlig zufällig ;-)).

Kann ich den GCC nicht überreden, den Reset-Vektor gleich richtig zu 
programmieren?

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Der Aufruf von "main" gehört - nach meinem Verständnis - auch nicht in 
den Resetvektor. Es ist Aufgabe des Startupcodes "main" auszuführen.
Genauso ist es dessen Aufgabe, den Returnwert von "main" zu 
interpretieren - selbst wenn er diesen "verwirft"...

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Ist es Dir vielleicht möglich, das komplette Projekt, ohne irgendwelche 
Verbiegungen irgendwelcher Vektoren, fertig Kompiliert mit allen 
zwischenfiles zu zippen und mal hier anzuhängen? Ich würde mir das gerne 
mal ansehen. Und zwar das, was sich die Entwickler des Startupcodes 
haben einfallen lassen...

von Florian P. (florianpose)


Angehängte Dateien:

Lesenswert?

Patrick Dohmen wrote:
> Ist es Dir vielleicht möglich, das komplette Projekt, ohne irgendwelche
> Verbiegungen irgendwelcher Vektoren, fertig Kompiliert mit allen
> zwischenfiles zu zippen und mal hier anzuhängen?

Klar. Ist angehängt...

In dieser Version ist also der Reset-vektor nicht gesetzt.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Auf der "fischl"-Site ist doch ein Blinkbeispiel angeführt.
Dort ist im "main.c" beschrieben, daß man eine Datei namens "reset.S" 
erstellen soll, die den Code für den Resetvektor enthält.

Hast Du dieses Beispiel mal ausprobiert?

von Florian P. (florianpose)


Lesenswert?

Patrick Dohmen wrote:
> Auf der "fischl"-Site ist doch ein Blinkbeispiel angeführt.
> Dort ist im "main.c" beschrieben, daß man eine Datei namens "reset.S"
> erstellen soll, die den Code für den Resetvektor enthält.
>
> Hast Du dieses Beispiel mal ausprobiert?

Ich habe es mir angesehen, und festgestellt, dass es nur für den R8C 
passt.

Mittlerweile habe ich mein Programm zum Laufen bekommen - und zwar nicht 
mit nur mit dem Startup-Code der GCC (bzw. newlib/libgloss) sondern auch 
mit einem, den ich mir von einem Beispiel der KPITGnuTools abgeschaut 
habe, was dazu geführt hat, dass das .mot-File nicht 26K sondern nur <1K 
groß ist. ;-)

Das Problem war das Flash-Programm: Der M16C-Flasher (mit 
R8C-Erweiterung), der auf 
http://www.fischl.de/thomas/elektronik/r8c/r8c_flasher.html empfohlen 
war, arbeitet wohl nicht ganz richtig. Mit dem M16C-Flasher von 
http://www.m16c-flasher.de hat es geklappt. Leider gibt es diesen nur 
für Windows.

Mit welchen Flashern (unter GNU/Linux) arbeitet Ihr?

Viele Grüße und vor allem vielen Dank,
Florian

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.