Forum: Compiler & IDEs C30 Code vor RAM-Initialisierung


von Michael (Gast)


Lesenswert?

Hallo,

Ich nutze für ein Projekt mit einem dsPIC den C30-Compiler von 
Microchip, welcher auf dem GCC basiert.

Folgendes Problem habe ich: Ich möchte etwas Code (I/O-Initialisierungen 
usw.) vor der RAM-Initialisierung ausführen.

Wie kann ich hier am einfachsten vorgehen?

Folgendes habe ich bereits versucht:

1. Ich habe eine eigene Section im Linker-Script geschaffen "io_init" 
und versucht eine Methode in diese Section per Attribut abzulegen. Dies 
funktioniert auch soweit, scheitert allerdings daran, dass der Compiler 
zum Ende der Methode einen "return"-Befehl erzeugt.

Das Programm kann dadurch nicht funktionieren, da der Stack zu diesem 
Zeitpunkt noch gar nicht verfügbar ist.

Ich habe keine Möglichkeit gefunden, den Compiler an der Erzeugung 
dieses Befehls zu hindern. (Eine Möglichkeit wie "naked" beim avr-gcc 
scheint es beim C30 nicht zu geben.)

2. Ich habe versucht meine I/O-Initialisierung direkt in 
Maschinensprache selbst zu schreiben. Dabei kann ich natürlich nach 
Belieben Befehle weglassen.

Aber hier kommt das nächste Problem: Der Assembler erlaubt nur ".section 
.text". Schreibe ich jedoch ".section .io_init" gibt er mir zu 
verstehen, dass er Code nicht im Datenbereich ablegen könne.

Wer weiß Rat?

Am besten würde es mir gefallen, wenn ich die Initialisierung selbst 
auch gleich in C schreiben könnte und nur die Erzeugung des 
"return"-Befehls irgendwie umgangen würde.

Microchip hat eine Section "user_init" vorgesehen. Diese ist allerdings 
Unsinn, da sie unmittelbar vor "main" aufgerufen wird. Die ganzen 
statischen Variablen usw. sind dann allerdings schon initialisiert.


Liebe Grüße,

Michael

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Soweit erinnert (kenne C30 nur aus Dokumentation) wird der Quellcode der 
Startupsequenz mitgeliefert. Diesen Quellcode (in crt0.S?) als Vorlage 
nehmen um den Aufruf der eigenen Initialisierung ergänzen. Falls 
Initialisierung in C geschrieben ist, vor dem Aufruf zumindest 
Stackpointer setzen. Eigene Startupdatei in Projekt/Makefile aufnehmen, 
assemblieren und linken. In der Map-Datei nachsehen, ob tatsächlich der 
eigene Startupcode gelinkt wurde und nicht der aus einer Library. Falls 
eigener nicht gelinkt wurde, Linkerreihenfolge und Linkeroptionen 
prüfen.

von Michael (Gast)


Lesenswert?

Hallo Martin,

Vielen Dank für deinen Tipp! Der ist echt Gold wert.

In der Datei "crt0_standard.s", welche sich im ZIP-Archiv "libpic30.zip" 
im Unterverzeichnis "src" des C30-Installationsverzeichnises befindet, 
steht folgender Code:
1
        mov      #__has_user_init,w0
2
        cp0      w0                ; user init functions?
3
        bra      eq,1f             ; br if not
4
        call     __user_init       ; else call them
5
1:

Diesen habe einfach von seiner bisherigen Stelle kurz vor dem Aufruf von 
"main" unmittelbar hinter die Initialisierung des Stack-Pointers 
verschoben, zum Projekt hinzugefügt, assembliert und neu gelinkt.

Funktioniert wunderbar! Durch die Abfrage davor gibt es noch nicht 
einmal einen Linkerfehler wenn die Methode im C-Code nicht existiert. 
Und am Linker-Script muss auch nichts geändert werden.

Die Methode muss dafür natürlich in der richtigen Section stehen:
1
__attribute__((section(".user_init"))) void init(void)

So habe ich es mir vorgestellt. Nochmals Danke.


Liebe Grüße,

Michael

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.