Forum: Compiler & IDEs main()-Funktion umbenennen bzw. ersetzen


von Le X. (lex_91)


Lesenswert?

Morgen,

gibt es beim gcc (insbesondere avr-gcc) eine Möglichkeit, die 
main-Funktion umzubenennen?
Das könnte sich evtl als nützlich erweisen für das was ich gerade 
probier :-)
Mit Umbenennen meine ich dass, nach Abarbeitung des StartUp-Codes eben 
nicht main() sondern z.B. myMain() angesprungen wird.
Aber ich fürchte ja, dieser Sprung ist fest in den StartUp-Code 
codiert...

Was ich nicht will, bzw. nicht geht:
1) Mit Makros und #ifdefs zur Compilezeit zwischen zwei main()s 
umschalten. Auserdem müsste dazu bestehender Code angefasst werden.

2) Der Parameter -e des gcc-Linkers ist mir bekannt. Damit kann ich den 
Einsprungspunkt meines Programmes festlegen. Aber so wie ich das 
verstehe ist dieser standardmäsig _start, also der Beginn des 
StartUp-Codes. Ändere ich diesen also, so wird mein Prozessor nicht 
initialisiert und mein Programm dementsprechend nicht laufen (kein 
Stack, keine globalen Variablen etc...)

Gibts da was?
Grüße!

von abc.def (Gast)


Lesenswert?

probiere mal hier im makefile:

# Target file name (without extension).
TARGET = main

Ich habe das jetzt nicht ausprobiert, aber hatte mal einen 
Bastel-Bausatz, da hieß das 'test'

von Le X. (lex_91)


Lesenswert?

Ohne dein makefile zu kennen rate ich jetzt einfach mal:
TARGET ist in deinem makefile die Variable die den Namen des Executables 
(und wahrscheinlich auch des Hex-Files) festlegt.

Danke für den Versuch, aber das ist sehr weit am Thema vorbei :-)

von Peter II (Gast)


Lesenswert?

Ich denke nicht das das geht, zumindest nicht als Parameter für den GCC. 
Denn der StartUp code kommt ja nicht vom Compieler sondern von der 
Runtime (eine Lib?). Dort ist ja die Reihenfolge festgelegt.

Wenn du das ändern willst, musst du dir eine andere Runtime bauen und 
diese als Startcode angeben.

von Sean G. (atmega318)


Lesenswert?

Was spricht gegen
main()
{
     Mymain();
}
?
Kann auch sein dass ich deine Frage falsch verstanden hab.

von Helmut S. (helmuts)


Lesenswert?

Sean Goff schrieb:
> Was spricht gegen
> main()
> {
>      Mymain();
> }
> ?
> Kann auch sein dass ich deine Frage falsch verstanden hab.

Aber das kostet doch ein paar Bytes vom RAM. :-)

Tipp: Da man nie zurückspringen will kann man die "verloreren" Bytes ja 
gefahrlos anderweitig wieder benutzen.

von Peter II (Gast)


Lesenswert?

Helmut S. schrieb:
> Aber das kostet doch ein paar Bytes vom RAM. :-)

dann nimm eine goto

von Lutz H. (luhe)


Lesenswert?

ich würde auch immer eine main nehmen,

und dort in  myMain() und die andere _main verzweigen,

Denn alle c Programme  fangen bei main an.

von Hermann-Josef (Gast)


Lesenswert?


von Le X. (lex_91)


Lesenswert?

Sean Goff schrieb:
> Was spricht gegen
> main()
> {
>      Mymain();
> }
> ?

Mein erster Beitrag, wo ich schrub:
>Was ich nicht will, bzw. nicht geht:
>1) Mit Makros und #ifdefs zur Compilezeit zwischen zwei main()s
>umschalten. Auserdem müsste dazu bestehender Code angefasst werden.

Ok, deine Lösung hat keine Makros, aber ich muss bestehenden Code 
(nämlich die "richtige" main) umschreiben.
Alle darauffolgenden Antworten (goto etc.) bringen das selbe Problem mit 
sich.

Und ja, ich denke auch nicht dass des als gcc Parameter geht, da eben 
wahrscheinlich der StartUp-Code geändert werden muss.
Aber hätte ja sein können dass die gcc-Experten da mehr wissen :-)

von Le X. (lex_91)


Lesenswert?

Hermann-Josef schrieb:
> und was ist mit dem Umschreiben der .init9-Section?

Das ist prinzipiell möglich. Aber dann muss ich noch eine zweite Version 
des StartUp-Codes bereithalten und beim make-Aufruf gegen diese Version 
linken.
Bzw. eben per -e Parameter in die _start dieses Alternativ-StartUp-Codes 
springen.
Aber ich werde das mal weiter verfolgen, denn das geht schon sehr in die 
Richtung die ich mir vorstelle.
Der Code soll nicht angefasst werden, lediglich der Compiler-Aufruf soll 
steuern, ob main() oder myMain() aufgerufen wird.
Dann kann man sich auch bequem dafür ein extra Target im Makefile 
anlegen.

Eigentlich geht das in Ordnung. Nachteil ist, bei einem Update der 
Toolchain muss der Alternativ-StartUp-Code neu erstellt werden.

Am Bequemsten wär eben ein Linker-Flag, aber sowas gibts wohl nicht :/

von Peter II (Gast)


Lesenswert?

le x. schrieb:
> Am Bequemsten wär eben ein Linker-Flag, aber sowas gibts wohl nicht :/

oder man schreibt sich einen Patch. main wird doch auch nur 
angesprungen, also braucht man nur die Sprungadresse auf deine mymain zu 
ändern. Das sollte schon mit einem script und der lss Datei möglich 
sein.

von Udo S. (urschmitt)


Lesenswert?

Die eigentliche Frage ist doch eher, warum braucht der TO das oder meint 
es zu brauchen.
Ich wette es gibt ne bessere Lösung als ein alternatives (2.) main().

von Karl H. (kbuchegg)


Lesenswert?

wenn schon makefile, dann würde ich im makefile zwischen zwei C-Files 
umschalten, die zum jeweiligen Projekt gehören. Beide enthalten ihr 
eigenes main(), aber nur eines der beiden wird compiliert und gelinkt, 
abhängig vom Target.

von Luther B. (luther-blissett)


Lesenswert?

le x. schrieb:
> Der Code soll nicht angefasst werden, lediglich der Compiler-Aufruf soll
> steuern, ob main() oder myMain() aufgerufen wird.

Du musst doch den Code nicht anfassen um das mit Makros zu lösen. Und 
wie kommst du auf #ifdef?

# prog.c enthält "MyMain()":
avr-gcc -c -DMyMain=main prog.c

von Karl H. (kbuchegg)


Lesenswert?

Udo Schmitt schrieb:
> Die eigentliche Frage ist doch eher, warum braucht der TO das oder meint
> es zu brauchen.
> Ich wette es gibt ne bessere Lösung als ein alternatives (2.) main().

Jau. Würde mich auch interessieren. Vor allen Dingen, warum dazu der 
Code nicht angefasst werden darf.
Denn eines haben diese Hintenrum-Lösungen alle gemeinsam. Zuerst hält 
man sie für eine wahnsinnig tolle Idee. Nach 3 Wochen kennt sich keiner 
mehr aus. Nach einem halben Jahr hat man den Trick schon längst wieder 
vergessen. Und nach einem 3/4 Jahr verflucht man sich selber, weil man 
bei der Reanalyse, was man da eigentlich gemacht hat, ums verrecken 
nicht mehr drauf kommt, wie und warum das eigentlich funktioniert.
Um wieviel einfacher wäre ein #define gewesen, dass man im Code 
kommentieren kann, so dass alles beisammen bleibt.

von Le X. (lex_91)


Lesenswert?

Udo Schmitt schrieb:
> Die eigentliche Frage ist doch eher, warum braucht der TO das oder meint
> es zu brauchen.
> Ich wette es gibt ne bessere Lösung als ein alternatives (2.) main().
Jaja, immer die TOs die sich einbilden, irgendwas brauchen zu würden.
Vielleicht interessiert mich eher die akademische Natur der Sache? 
Toolchain Internas, etc.

Aber OK:
Gegeben sei ein mittelgroßes Projekt (für ATmega-Verhältnisse :-)).
Dieses erstreckt sich über mehrere Module, von denen einige fertig sind, 
manche sich aber auch noch in der Entwicklung befinden.
Manchmal will man vielleicht eine neue Funktion, einen Algorithmus, eine 
Umrechnung schnell mal testen. Und zwar völlig spontan.
Nicht erst die Bedinungen herstellen die überhaupt notwendig sind damit 
diese Funktion aufgerufen wird, oder warten bis irgendwelche Ereignisse 
eintreten die diese Funktion triggern.
Kurz: Prozessor flashen, Funktion wird abgearbeitet. Schön wäre es, wenn 
man dafür ein Target hätte, die dieses Feature bereitstellt. Dann ist es 
ein Befehl in der Shell, oder ein Klick, je nach Vorlieben.
Nicht erst die main.c öffnen, irgendwas auskomentieren, Funktionsaufruf 
einfügen usw. Kurz: nicht in Sourcen rumklauben die fertig sind.
Denn mal ehrlich, wer kennt es nicht? Du entwickelst, probierst rum, 
kommentierst Dinge aus, verunstaltest existierenden Code. Und wenn dann 
alles läuft wird garantiert nicht mehr aufgeräumt...

Ich sehe auch nicht das von KHB angesprochene Problem, das man den 
Mechanismus dahinter "vergisst" und deswegen mit #defines arbeiten 
sollte.
Ganz im Gegenteil: wenn jemand meine Sourcen durchsieht muss er sich 
nicht erst fragen was denn da überall für Artefakte im Code 
rumschwirren, welche seltsamen defines die main() umhüllen, wo denn 
diese defines gesetzt werden und was noch notwendig ist um ein Feature 
zu nutzen, das er nicht braucht.
Nein, ich muss nur ein Target aus dem MF löschen und alle Spuren meines 
Workarounds sind verschwunden.

Auch wenn manchen die Fantasie vielleicht fehlt, wo hier der konkrete 
Nutzen wäre: ich hätte einen, und zwar erheblich.
Leider wird sich nun die Diskussion in eine völlig andere Richtung als 
meine ursprüngliche Frage entwickeln. Aber ich denke, ich hab meine 
Antwort eh schon :-)

Viele Grüße!

von Oliver (Gast)


Lesenswert?

le x. schrieb:
> Jaja, immer die TOs die sich einbilden, irgendwas brauchen zu würden.

Die kennen halt alle Java, und setzen solche Annehmlichkeiten einfach 
voraus.

Aber ganz ehrlich, bei Projekten in der Größe eines handelsüblichen 
Bastler-AVR-Programms kann man sich ja nun problemlos angepasste Kopien 
von main anlegen. Die sind dann schnell per Hand umbenannt, und genauso 
schnell auch wieder gelöscht.

Mit #define und #if im Originalcode herumzufuhrwerken ist nicht die 
Lösung.

Oliver

von Stefan Noack (Gast)


Lesenswert?

le x. schrieb:
> Denn mal ehrlich, wer kennt es nicht? Du entwickelst, probierst rum,
> kommentierst Dinge aus, verunstaltest existierenden Code. Und wenn dann
> alles läuft wird garantiert nicht mehr aufgeräumt...

Kein Versionskontrollsystem?! Ich würde einfach meinen Testaufruf in die 
main.c machen, diese aber dann nicht einchecken und nötigenfalls 
zurücksetzen.

Alternativ ginge auch folgendes im Makefile:
1
test:
2
  mv main.c main.c.orig
3
  cp test.c main.c
4
  make
5
  mv main.c.orig main.c

von Le X. (lex_91)


Lesenswert?

> Mit #define und #if im Originalcode herumzufuhrwerken ist nicht die
> Lösung.

Natürlich nicht. Das predige ich ja selbst schon seit Beginn an :-)

>
> Kein Versionskontrollsystem?! Ich würde einfach meinen Testaufruf in die
> main.c machen, diese aber dann nicht einchecken und nötigenfalls
> zurücksetzen.

Doch natürlich, benutze hier git.
Klar geht das, aber ich wünsche mir halt immer noch irgendwie die 
Ein-Klick-Lösung (respektive ein-Kommando).

Mir ist aber noch was gekommen, das werd ich so mal testen:
Ganz normal Kompilieren, aber vorm Linken mittels strip das Symbol 
"main" aus der main.o entfernen.
Meine zu testende Funktion muss dann natürlich main() heißen oder von 
einer dummy-main() aufgerufen werden, aber das ist noch tragbar, da sich 
das alles innerhalb der aktuellen c-Datei abspielt. Evtl. kann man diese 
Funktion kurz im Quelltext kennzeichnen, etwa so wie die avr-libc das 
mittels ISR macht. Das Ganze kann man dann in einem Header verstecken.

von Markus (Gast)


Lesenswert?

Pack doch jede deiner main()-Funktionen, und nur diese, in verschiedene 
C-Files. Das ergibt beim compilieren unterschiedliche Object-Files und 
je nach Build-Target übergibst du dem Linker das entsprechende 
Object-File.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

le x. schrieb:
> Kurz: Prozessor flashen, Funktion wird abgearbeitet. Schön wäre es, wenn
> man dafür ein Target hätte, die dieses Feature bereitstellt. Dann ist es
> ein Befehl in der Shell, oder ein Klick, je nach Vorlieben.

Dann schreibe doch gleich, dass Du so etwas haben willst. Stattdessen 
führst Du alle Mitleser und -schreiber absichtlich in die Irre, indem Du 
eine komplett andere Frage stellst.

Die Lösung ist nämlich viel, viel einfacher als sämtliche Basteleien mit 
Präprozessordirektiven oder Eingriffen in den Startvorgang: man erstelle 
einfach mehrere Quelltexte, in denen die entsprechenden 
main()-Funktionen implementiert sind. Und im Makefile oder der IDE 
konfiguriert man eben mehrere Targets, in denen die Kompilate der 
unterschiedlichen Quelltexte angezogen werden. Fertig ist die Laube.

von Udo S. (urschmitt)


Lesenswert?

Informiere dich mal über "test driven development".
Schreibe dir halt für einzelne Funktionen und Module eigene Tests die 
jeder ein main haben.
Die Tests kannst du dann bei jeder Änderung am Code wieder benutzen, 
bzw. bei einer Portierung mit portieren und kannst damit sofort das 
portierte testen.
Braucht nur etwas Organisation und schon kannst du die gesamte Frickelei 
weglassen.

le x. schrieb:
> Jaja, immer die TOs die sich einbilden, irgendwas brauchen zu würden.
Nein, immer die TOs, die meinen ihr kruder Ansatz wäre der einzige Weg.

von lex (Gast)


Lesenswert?

Andreas Schweigstill schrieb:
> Dann schreibe doch gleich, dass Du so etwas haben willst. Stattdessen
> führst Du alle Mitleser und -schreiber absichtlich in die Irre, indem Du
> eine komplett andere Frage stellst.

Nö. Ich habe genau die Frage gestellt, die mich interessiert hat.
"Kann man mit gcc eine andere Funktion außer main() als erste C-Funktion 
anspringen?"
Eine Antwort darauf hab ich zwar nicht bekommen, kann mir aber 
mittlerweile selbst zusammenreimen dass es erstmal nicht geht, da der 
Sprung hartcodiert im StartUp-File liegt.

> man erstelle einfach mehrere Quelltexte, in denen die entsprechenden
> main()-Funktionen implementiert sind. Und im Makefile oder der IDE
> konfiguriert man eben mehrere Targets, in denen die Kompilate der
> unterschiedlichen Quelltexte angezogen werden.

Viel, viiieel mehr Aufwand als wenn man die main() ändern könnte. 
Mehrere Quelltexte mit einer main()? Und dann noch mehrere Targets? Für 
was? Brauch ich nicht, für das was ich will. Auch viel mehr Arbeit als 
meine Methode mit strip.
Genauso wie der Beitrag von Udo Schmitt.
"test driven development"? Module Tests? Wo hab ich denn sowas 
geschrieben?
Und dabei wollt ich doch nur kurz und unkompliziert z.B. meine 
atoi()-Implementierung testen...


Also, ohne jetzt unfreundlich klingen zu wollen:
Genau deswegen hab ich nicht geschrieben was ich vorhabe. Ist klar dass 
es für jedes Problem 1000 mögliche Lösungen gibt. Und leider wird in 
meine Beschreibung meines Vorhabens was ganz anderes hineininterpretiert 
als ich vorhabe. Siehe Udo Schmitt und seine Module Tests. Der nächste 
schlägt mir dann vor, meine Testvektoren nicht mit Matlab/Simulink 
sondern mit Tool X zu generieren, weil das ja viel besser geht. Nur wo 
hab ich sowas gefragt?
Genau deswegen formuliere ich meine Frage kurz und knapp und eindeutig 
beantwortbar.

Ich werde meine Methode heut mal Testen und dann evtl. berichten. Wenn 
noch was kommt freu ich mich, aber eigentlich seh ich den Thread als 
gelaufen an, wir sind jetzt im Stadium "Diskussion und Wortklauberei" 
angekommen :-)
Hm, ich könnt das ganze ja offiziell machen und einen 3.-Reich-Vergleich 
bringen, dann weiß auch jeder dass es vorbei ist :-)

Viele Grüße!

von Karl H. (kbuchegg)


Lesenswert?

lex schrieb:

>> man erstelle einfach mehrere Quelltexte, in denen die entsprechenden
>> main()-Funktionen implementiert sind. Und im Makefile oder der IDE
>> konfiguriert man eben mehrere Targets, in denen die Kompilate der
>> unterschiedlichen Quelltexte angezogen werden.
>
> Viel, viiieel mehr Aufwand als wenn man die main() ändern könnte.
> Mehrere Quelltexte mit einer main()? Und dann noch mehrere Targets? Für
> was? Brauch ich nicht, für das was ich will. Auch viel mehr Arbeit als
> meine Methode mit strip.

Aber straight forward und wäre schon längst fertig, wenn du um 13:00 
angefangen hättest.

von Udo S. (urschmitt)


Lesenswert?

le x. schrieb:
> Nicht erst die main.c öffnen, irgendwas auskomentieren, Funktionsaufruf
> einfügen usw. Kurz: nicht in Sourcen rumklauben die fertig sind.
Darum eigene Testprogramme

lex schrieb:
> Module Tests? Wo hab ich denn sowas geschrieben?
Gar nicht, ich bin idealistischerweise davon ausgegangen, daß du bereit 
bist was neues zu lernen.

lex schrieb:
> Ist klar dass es für jedes Problem 1000 mögliche Lösungen gibt.
Gute und weniger gute, du scheinst dich für weniger gute zu entscheiden.

Viel Spass damit solange du Software nicht mal professionell entwickeln 
musst.

von Gelöscht (kami89)


Lesenswert?

Würdest du denn beim Testen gerne angeben können, welche Funktion nun 
anstelle der main() angesprungen wird, oder soll es einfach quasi eine 
main2() Funktion geben, die immer die selbe ist?

lex schrieb:
> Und dabei wollt ich doch nur kurz und unkompliziert z.B. meine
> atoi()-Implementierung testen...

Diese atoi() Funktion wird ja vemutlich Parameter und Rückgabewert haben 
(und auch wenn nicht, es könnte mal eine Funktion geben, die du testen 
möchtest, die Parameter und Rückgabewert haben), oder? Dann bringt dir 
das direkte Anspringen dieser Funktion ja nicht viel, da du dann weder 
Parameter übergeben, noch den Rückgabewert überprüfen kannst.

Also müsstest du für jede zu testende Funktion auch eine eigene 
main()-Funktion machen, die dann die zu testende Funktion mit diversen 
Parametern auf korrekte Arbeitsweise überprüft (was ja wie schon erwähnt 
Richtung Modultests geht).

Oder sollen deine zu testenden Funktionen immer nur void foo(void) 
Funktionen ohne Parameter und Rückgabewert sein?

von lex (Gast)


Lesenswert?

Haja, ich wollt eigentlich nichts mehr dazu schreiben, aber wieso nicht, 
ist eh schon egal :-)

> Gar nicht, ich bin idealistischerweise davon ausgegangen, daß du bereit
> bist was neues zu lernen.
Module Tests kenn ich. Brauch ich nicht, zumindest nicht daheim im 
Bastelkeller. Was neues lernen? Siehst, du interpretierst schon wieder 
viel zu viel. Du triffst annahmen was ich weiß und was nicht, und was 
ich brauchen könnte.

> Gute und weniger gute, du scheinst dich für weniger gute zu entscheiden.
Hm du leidest am selben Syndrom was du mir vorwirfst: Zu denken der 
eigene krude Ansatz wär der Beste Weg.

> Viel Spass damit solange du Software nicht mal professionell entwickeln
> musst.
Tu ich schon.
Soll ich dir verraten, in welche Fahrzeuge du zukünftig lieber nicht 
mehr einsteigen solltest? Ne, ich lass dich im Ungewissen :-)

Schönen Tag noch zusammen

von Oliver (Gast)


Lesenswert?

lex schrieb:
> Nö. Ich habe genau die Frage gestellt, die mich interessiert hat.
> "Kann man mit gcc eine andere Funktion außer main() als erste C-Funktion
> anspringen?"
> Eine Antwort darauf hab ich zwar nicht bekommen, kann mir aber
> mittlerweile selbst zusammenreimen dass es erstmal nicht geht, da der
> Sprung hartcodiert im StartUp-File liegt.

Geht nicht gibts nicht. RTFM.

Aus .init8 kannst du in dein selbsternanntes main springen.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

lex schrieb:

> Kann man mit gcc eine andere Funktion außer main() als erste C-Funktion
> anspringen?

Lege die Funktion per section Attribut nach .init8 und gut is.

von lex (Gast)


Lesenswert?

Johann L. schrieb:
> Lege die Funktion per section Attribut nach .init8 und gut is.

Danke dir Johann!

von Mark B. (markbrandis)


Lesenswert?

Udo Schmitt schrieb:
> Die eigentliche Frage ist doch eher, warum braucht der TO das oder meint
> es zu brauchen.

Genau so ist es.

> Ich wette es gibt ne bessere Lösung als ein alternatives (2.) main().

Da verwett ich meinen A... drauf ;-)

von Udo S. (urschmitt)


Lesenswert?

lex schrieb:
> Soll ich dir verraten, in welche Fahrzeuge du zukünftig lieber nicht
> mehr einsteigen solltest?

Ich steige nur in Autos die mindestens schon 3 Jahre im Markt sind. Bis 
dahin haben deine Kollegen deine Fehler gefunden :-)

von Mark B. (markbrandis)


Lesenswert?

Udo Schmitt schrieb:
> le x. schrieb:
>> Jaja, immer die TOs die sich einbilden, irgendwas brauchen zu würden.
> Nein, immer die TOs, die meinen ihr kruder Ansatz wäre der einzige Weg.

Ihre Anzahl ist Legion.

So wie der Kollege, der selber ein Faxgerät entwickeln will, weil ihm 
andere Lösungen zu teuer sind. Mann Mann Mann...

Udo Schmitt schrieb:
> Ich steige nur in Autos die mindestens schon 3 Jahre im Markt sind. Bis
> dahin haben deine Kollegen deine Fehler gefunden :-)

Owned. :)

von lex (Gast)


Lesenswert?

Morgen zusammen,

lustig, dass hier manche gleich persönlich werden. Naja was solls. 
Dieses Forum hat mir schon soviele Stunden Popcornkino beschert, da geb 
ich gerne auch mal welches zurück :-)

An den Rest dens interessiert: dank Johann konnte ich gestern noch bisl 
was zusammenschustern, und meine Lösung macht genau das was es soll.
Bin schon sehr zufrieden, auch wenn ich noch nicht alles umgesetzt habe.
Vielleicht wird ja auch dem einen oder anderen klar, wieso ich die 
ursprüngliche Frage gestellt hab.

Was momentan geht:
Ich verwende eine leicht modifizierte Version des AVR Simulators 
"avrtest". Wenn ich im Code gewisse Marken setze und das Executable dann 
durch den Simulator jage krieg ich verschiedene Infos, z.B. die Takte 
die ein Block oder eine Funktion benötigt. Sehr interessant vor allem 
für ISRs.

Anwendung:
Gegeben sei ein Projekt mit mehreren Modulen. Ich arbeite gerade an 
einer Funktion foo() in irgendeiner c-Datei.
1
void foo(void)
2
{
3
    ...
4
}

Will ich mal eben die Laufzeit dieser Funktion messen so ersetz ich kurz 
den Funktionskopf:
1
CYCLE_COUNT_FUNC(foo)
2
{
3
    ...
4
}
Diese Schreibweise ist ja auch aus der avr-libc bekannt, für ISRs.

Danach tippe ich auf der Kommandozeile
1
make avrtest
 oder drücke den passenden Knopf auf meiner IDE.
Dadurch erhalte ich eine Ausgabe, ungefähr:
1
function cycle count: 123

Find ich schon sehr praktisch. Vor allem unter Linux, wo es kein AVR 
Studio zur Simulation gibt (nein, simulavr kommt da leider nicht ran).
Ich wüsst auch keine Möglichkeit, so eine Messung schneller 
durchzuführen. Vor allem, ohne in verschiedenen c-Dateien 
rumzukommentieren oder Aufrufe zu setzen/ändern. Denn je nach Projekt 
müssen ja auch Vorbedingungen hergestellt werden, die zum 
Funktionsaufruf führen. Funktioniert übrigens auch mit ISRs. Ich kann 
mein Zeugs also völlig losgelöst vom restlichen Projekt kurz 
analysieren.

So, nächstes Problem:
Ich arbeite an einer Funktion die Parameter übergeben bekommt:
1
char * myItoa (int value, char *str, int base);
Um diese Funktion zu testen muss sie irgendwie bespaßt werden. Auserdem 
ist zu erwarten dass unterschiedliche Aufrufe auch unterschiedliche 
Laufzeiten ergeben.
Zugegeben, das kann und werde ich noch bischen eleganter hinter Makros 
verstecken, aber momentan kann ich so vorgehen:

Ich muss mir (leider noch) eine kleine Helferfunktion schreiben. Dank 
Makros aber auch nicht so wild.
1
CYCLE_COUNT_MAIN
2
{
3
    CYCLE_COUNT_BLOCK
4
  {
5
      myItoa(123, buf, 8);
6
  }
7
}
Und erhalte ebenso meine Ausgabe, inklusiv Kosten für den Aufruf.
Zugegeben, hier muss ich schaun wie man das noch abkürzen könnt.
Nach getaner Arbeit wird dieses Konstrukt wieder entfernt.

Ich muss sagen, mir persönlich hat das gestern schon sehr geholfen, die 
ISR meiner BCM zu optimieren. Weil mich momentan hauptsächlich 
Laufzeiten interessieren habe ich bisher auch nur die Makros für die 
Anbindung an avrtest umgesetzt.

Wer solche Probleme nicht hat, - OK.
Aber ich wüsst jetzt nicht wie man sowas geschickter hätte lösen können.
Ich muss nicht in anderen Sourcefiles rumklabustern, keinen Code umher 
copy&pasten, keine Vorbedingungen für Simulatoren herstellen und habe 
keine Target-Orgien im makefile.
Mir persönlich ging es darum, so wenig wie möglich anfassen zu müssen. 
Die Messung soll wirklich ruck-zuck gehen und kein großes Überlegen 
erfordern: "Hm, wo wird diese Funktion aufgerufen, wann passiert das, 
was muss ich vorher eingeben?".

Viele Grüße

von lagom (Gast)


Lesenswert?

Doofe Frage, aber kann ich zum Takte einer ISR zählen nicht ziemlich 
einfach das Assembler-Listing auswerten lassen?
Ohne das Programm zu zerteilen usw.?

von Oliver (Gast)


Lesenswert?

Wenn das eine "klassische" ISR ist (rein , Flag setzen, raus), dann ja. 
Wenn allerdings da drin was ernsthaftes passiert, eher nicht (zumindest 
nicht einfach)

Oliver

von lex (Gast)


Lesenswert?

Oliver schrieb:
> Wenn das eine "klassische" ISR ist (rein , Flag setzen, raus),
> dann ja.
> Wenn allerdings da drin was ernsthaftes passiert, eher nicht (zumindest
> nicht einfach)
>
> Oliver

Globale Variablen müssen natürlich bespaßt werden.
D.h. ich muss sie auf den Wert initialisieren der mich in den zu 
testenden Pfad führt. Das musst aber immer, auch im Simulator.
Und ich weiß, dass meine ISR genau diesen Pfad durchlaufen wird, den ich 
vorgebe.

von Rolf Magnus (Gast)


Lesenswert?

lex schrieb:
> Nö. Ich habe genau die Frage gestellt, die mich interessiert hat.
> "Kann man mit gcc eine andere Funktion außer main() als erste C-Funktion
> anspringen?"

Wenn du C++ nimmst, geht das dort direkt mit Sprachmitteln. Dort kann 
man Klassen definieren, und beim Instanziieren wird der Konstruktor 
aufgerufen,  oder man kann eine Variable anlegen und mit dem Returnwert 
einer Funktion initialisieren. Bei globalen Objekten wird der Aufruf 
dann vor main() gemacht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Und in GNU-C gibt's auch attribute constructor, mit dem man Funktionen 
vor main() ausführen kann.  Diese Constructors werden zum Zeitpunkt 
ausgeführt wie statische C++ Konstruktoren auch.

von lex (Gast)


Lesenswert?

Danke euch beiden, gibt ja doch einiges an Möglichkeiten.
Ich bin momentan ganz zufrieden so, läuft alles wie es soll! Ob ich 
meine Funktion jetzt direkt nach .init8 lege oder als Konstruktor 
deklariere (der dann im Prinzip auch in einer .init-Sektion liegt) ist 
dann wohl Geschmacksache...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Nein, der Constructor liegt eben nicht in der .init-Section; er wird nur 
von dort aus aufgerufen.  Der Unterschied ist, dass er deshalb nicht 
naked sein darf im Gegensatz zu "normalen" init-Funktionen, die naked 
sein müssen und daher begrenzten Funktionsumfang haben.  Für letztere 
ist nur das Funktionieren von Inline-Assembler garantiert.

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.