Linker meldet "undefined reference"



  • Moin zusammen,

    ich benutze für ein Embedded Project den GCC 4.2.8 von Codesourcery für Freescale Coldfire Prozessoren. Hierzu erstelle ich eine Library mittels ar. In dieser Lib befindet sich "OSManager.o" (von mir geschrieben), das aus "OSManager.h" / "OSManager.c" besteht. Alles in C89 geschrieben.
    In diesem "OSManager.c" gibt es eine InterruptServiceRoutine (ISR). Das von mir benutzte OS namens uCos-II (ein Embedded OS) verlangt allerdings, dass die erste Instruktion das Sperren der CPU Interrupts ist, da es sonst Probleme mit dem Scheduler gibt, falls der einen Context Switch durchführen möchte. Somit kann ich die ISR nicht ausschließlich in C schreiben, da der Compiler natürlich zuerst Code erzeugt, um die benutzten CPU-Register auf den Stack zu sichern.

    Also habe ich folgendes gebastelt (in "OSManager.c"):

    asm("MeineISR:\n");
    asm(.... hier Code um Interrupts zu sperren...);
    

    In "OSManager.h" dann

    extern void MeineISR(void);
    

    Das compiliert prächtig in die Lib. Versuche ich nun aber diese Lib mit meiner Hauptapplikation zu linken, findet ld das Symbol "MeineISR" nicht.
    Wie teile ich ld nun mit, dass es das Symbol "MeineISR" in der Lib gibt.
    Ein Makefileproblem ist es nicht, denn alles andere in der Lib findet er, wenn ich in der Hauptapplikation den Zugriff auf das Symbol "MeineISR" mit #if 0 ausklammere.

    Any idea?

    thanx, Arne

    PS: ich kann auch gerne noch etwas weiter ausholen, falls gewünscht.



  • das problem ist: es gibt das symblo MeineISR nicht. Du hast lediglich ein label angelegt und ein label ist nichts anderes als ein hilfsmittel für uns menschen um jumps besser lesen zu können.

    ich verstehe das problem nicht genau: du meinst die 1. aktion in einer bestimmten funktion muss das sperren der cpu interrupts sein. das geht aber nicht in c, weil c erstmal register auf den stack/in register packt.

    kannst du nicht einfach einen wrapper um deine ISR funktion schreiben die nichts anderes macht als die interrupts zu sperren und dann die relevante funktion aufzurufen?

    ob du die funktion in asm oder c schreibst: wenn du sie aus heraus aufrufen willst, wird er dir immer die argumente auf den stack/in register packen. aber uU hat dein compiler ja eine passende calling convention für die funktion wo die aktionen die die CPU nicht mag, nicht ausgeführt werden.



  • bei gcc's heisst das wahrscheinlich __attribute__((interrupt)) oder __attribute__((interrupt_handler)) d.h. deine isr könnte so aussehen.

    void MeineISR (void) __attribute__((interrupt)) // oder: __attribute__((interrupt_handler)) 
    {
     ...
    }
    

    wenn du alles selber machen willst, dann verpass der funktion das __attribute__((naked)) dann wird kein entry/exit code erzeugt.

    btw: gcc's für MCU sind echt ein krampf. nimm besser das: http://www.freescale.com/webapp/sps/site/overview.jsp?nodeId=01272694014080
    🙂



  • Moin zusammen,

    du meinst die 1. aktion in einer bestimmten funktion muss das sperren der cpu interrupts sein. das geht aber nicht in c, weil c erstmal register auf den stack/in register packt.

    Exakt das ist das Problem: gcc für m68k/Coldfire versucht (zumindest in meiner Version) immer zuerst die Register D0/D1 & A0/A1 auf den Stack zu retten, selbst wenn er nicht alle Register benutzt (in Optimierungsstufe -O0).

    kannst du nicht einfach einen wrapper um deine ISR funktion schreiben die nichts anderes macht als die interrupts zu sperren und dann die relevante funktion aufzurufen?

    Exakt das hatte ich vor (mittels Label) und bin dabei auf die Linkermeldung gestossen (worden) 🙄
    Mein Gedanke war etwas in dieser Art:

    #define INTERRUPT(function, statusreg)		asm (#function ":\n");\ 
    asm ("move.w	#" #statusreg ",%sr\n");	\
    static void (function ## Main) (void)
    

    Der Aufruf wäre dann gewesen:

    INTERRUPT(MeineISR, 0x2700);
    

    Die Funktionsdeklaration mittels

    static void MeineISRMain(void)
    

    wäre nur ein Dummysprungziel gewesen, damit ich dann ganz problemlos einen { } Block öffnen könnte.

    @pale dog:
    __attribute__((interrupt_handler)) weist den gcc nur an die Funktion mit rte (Return from Exception) und nicht mit rts (Return from Subroutine) zu beenden. Mit rte wird dann zusätzlich zur Rücksprungadresse noch das Statusregister restauriert.
    Aber __attribute__((naked)) war dann letztendlich exakt das, was ich suchte 🙂
    Bei http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html steht allerdings der m68k/Coldfire nicht als Target für naked drin, deshalb habe ich dieses Attribut nicht berücksichtigt.

    Mit dem GCC kommen wir prima klar (wenn man die Attributes alle richtig zu deuten weiß 😉 ). Klar, CodeWarrior wäre auch schön, aber wenn ich Geld ausgeben dürfte, dann wohl eher das System von Greenhills 😃

    Viele Dank Euch beiden für die Hilfe!

    Thanx, Arne



  • Die Lösung über compilerspezifische Sachen wäre definitiv am besten.

    Wenn das aber nicht geht, dann sollte dein code so laufen können:

    #define INTERRUPT(statusreg, function) \
      asm ("move.w    #" #statusreg ",%sr\n");    \ 
      function
    
    //spaeter dann:
    
    INTERRUPT(0xdead, foo(1,2,3))
    //oder fuer rueckgaben:
    INTERRUPT(0xdead, i=bar())
    

    denn was ich nicht verstehe: wozu willst du ein label haben, was bringt es dir? und den sinn der deklaration von ISRMain kapiere ich auch nicht.



  • Die Lösung über compilerspezifische Sachen wäre definitiv am besten.

    So sehe ich das auch.

    Mit Deiner Lösung würde er aber bei Aufruf von function auch an function springen und nicht die asm(..) Anweisung zum Sperren der Ints ausführen 😉
    Oder ich müßte ihn an function - 4 springen lassen, da die asm Anweisung 4 Bytes lang ist. Widerspricht aber meiner Programmierphilosophie. Irgendwann weiß dann keiner mehr warum "- 4" berechnet wurde. Und Kommentare werden von Unwissenden auch gerne mal gelöscht...

    wozu willst du ein label haben

    Damit ich ein Sprungziel habe. Irgendwohin muß die CPU doch bei Eintreten des Ints hinspringen und das muß ich ihr ja mittels Adresse (= Sprungziel) sagen.
    Nehme ich "function" als Sprungziel aus Deinem Macro, sperrt er die Ints nicht als allererstes!

    und den sinn der deklaration von ISRMain

    Ist wie gesagt nur ein Dummy, damit ich einen Block {...} öffnen kann. Könnte durchaus auch ohne gehen. Soll nicht der Aufhänger sein.

    Erste Ergebnisse auf dem Target: man darf wohl

    __attribute__((interrupt_handler))
    

    nicht mit

    __attribute__((naked))
    

    in der Deklaration kombinieren, da der gcc dann automatisch Entry/Exit Code erzeugt. Ich muß hier also meine Aussage revidieren, daß __attribute__((interrupt_handler)) lediglich für das rte sorgt und das Gegenteil behaupten. 🙄
    Mit __attribute__((naked)) alleine klappt es, auch wenn der Compiler meldet:
    OSManager.h:95: warning: 'naked' attribute directive ignored
    Ich werde da mal bei Codesourcery anfragen - da habe ich den Coldfire-GCC her.

    Er erzeugt trotzdem den korrekten Maschinencode, wie ich im Lauterbach ICD sehen kann. Der Code mit der ISR (100Hz Timer für uCos-II - ein Embedded OS) läuft prima seit 10min. Sonst ist er innerhalb der ersten 1/10sek. abgeschmiert.

    ciao, Arne



  • Du musst schon etwas mehr erklären.

    Was genau ist an meinem Makro jetzt das Problem? Irgendwann musst du ja in die Funktion springen, das wird dir nicht erspart bleiben solange du den Code in C schreiben willst.

    Erklär mal genau was gemacht werden muss.

    Aber wenn es jetzt passt, ists ja gut 🙂



  • Okay, dann mal langsam. Ich benötige die Adresse der ISR, damit ich sie in die Vectortable der CPU eintragen kann. Wenn jetzt Interrupt 42 auftritt, bildet die CPU ja mittels dieser 42 die Einsprungadresse in die ISR. Klar?
    Gut dann dröseln wir mal Dein Macro auf für folgende Deklaration

    INTERRUPT(0x2700, MeineISR);
    

    Das ergibt dann:

    asm("move.w	#0x2700,%sr\n");
    MeineISR
    

    Wenn ich die Adresse von der ISR haben will und nun MeineISR dazu nehme, welche Adresse würde nun in die Vectortable eingetragen? Die Adresse von MeineISR (was flasch wäre) oder die Adresse der asm-Anweisung (was richtig wäre). Oder anders: ich muss die Adresse der asm-Anweisung eintragen. Trage ich die von MeineISR ein, wird die asm-Anweisung ja NIE ausgeführt. Wie kriege ich den Compiler/Linker nun dazu mir die Adresse der asm-Anweisung zu liefern? Genau da war ich die Tage bei asm("MeineISR: move.w #0x2700,%sr\n") angelangt - nur der Linker wollte nicht.
    Jetzt klarer?

    Übrigens noch eine Richtigstellung: nachdem ich Rückmeldung von Codesourcery bekam, daß das naked Attribut eigentlich gänzlich unwirksam sein sollte beim Coldfire-Port des gcc, habe ich nochmals rumexperimentiert:

    1. Codesourcery hat recht - naked gibts beim Coldfire-Port nicht
    2. gcc erzeugt Entry/Exit Code (Pushen/Poppen von vier Registern), wenn man __attribute__ ((interrupt_handler)) benutzt
    3. benutzt man keine Attribut und legt auch keine lokalen Variablen an, dann wird kein Entry/Exit Code erzeugt.
    4. Sollte man lokale Variablen benötigen, müßte man m.E. auf static-Variablen ausweichen
    5. man muß sich dann aber auch selbst darum kümmern, daß "rte" als letzte Anweisung der ISR ausgeführt wird:
    void MeineISR(void)
    {
    	asm("move.w	#0x2700,%sr\n");
    	...
    	asm("rte")
    }
    
    1. Ich hab wohl viel Lärm um nix gemacht - sorry. Aber ich war davon überzeugt, daß immer Entry/Exit Code erzeugt wird - speziell bei attributlosen Funktionen

    BTW:

    INTERRUPT(0xdead, foo(1,2,3))
    INTERRUPT(0xdead, i=bar())
    

    Mir ist keine einzige Version bekannt, wo man einer ISR Werte übergeben kann (wer soll die denn auf den Stack legen?) bzw. wo man etwas als Funktionsergebnis bekommt (wer soll das denn dann abholen - Interrupts sind ja asynchrone Ereignisse.)

    thanx, Arne



  • ja, unser hochgelobter GCC eben 👎 😡
    übrigens: es gibt manchmal C gegen assembler flamewars in 'embedded-related' foren. dabei werden oft von seiten der asm-befürworter solche tollen GCC-features wie "der pusht ja 10 register auf den stack, braucht aber nur eins in der funktion" um zu beweisen, dass C nichts taugt. 🙂



  • ArneS schrieb:

    Das von mir benutzte OS namens uCos-II (ein Embedded OS) verlangt allerdings, dass die erste Instruktion das Sperren der CPU Interrupts ist ...

    Üblicherweise ist das hardwareseitig so geregelt, daß ein Prozessor kein Interrupt Cascading zuläßt, d.h., eine ISR ist eigentlich in ihrem Ring zunächst mal alleine.
    Der nächstinnere Ring kann da zwar reinspielen, aber die MMU sichert von sich aus den Kontext. Ich glaube nicht, daß das bei Freescale komplett anders ist.

    ArneS schrieb:

    Somit kann ich die ISR nicht ausschließlich in C schreiben, da der Compiler natürlich zuerst Code erzeugt, um die benutzten CPU-Register auf den Stack zu sichern.

    Wie kommst Du auf die Idee? Du mußt dem Compiler natürlich mitteilen, daß Du eine Interruptroutine haben magst, häufig heißt es dann

    #pragma interrupt FunctionName
    

    In der Vectortable dann noch das Label als global eintragen ... und fertig ist der Budenzauber. Wie das im Einzelnen heißt ->> Compiler Manual
    Wie die Int- Mechanismen Deines Prozessors ticken und wie der Scheduler davon Gebrauch macht ist auch eine eher spezielle Sache.

    Aber ganz sicher ist es nicht so, daß ISRs nicht in C schreibbar sind 😃



  • @pale_dog: Und die asm-Befürworter speichern sicher ihre Sourcen auch auf Lochkarte, oder? 😉
    Ich schau mir mal an, ob sich bei -O3 was ändert...

    @pointercrash():

    aber die MMU sichert von sich aus den Kontext. Ich glaube nicht, daß das bei Freescale komplett anders ist.

    das Dumme ist nur: Der Coldfire 5307 hat keine MMU! Das haben m.W. nur einige mit dem 4e Kern.

    Wie kommst Du auf die Idee? Du mußt dem Compiler natürlich mitteilen, daß Du eine Interruptroutine haben magst, häufig heißt es dann

    Und genau DAS hat mich bei uCos ins Verderben gerissen. Hast Du den ganzen Thread gelesen?

    #pragma interrupt FunctionName

    Genau DAS heißt beim GCC eben (wie pale dog richtig anmerkte):

    __attribute__ (interrupt_handler))
    

    Nur hat das zur Folge, daß der GCC nicht nur ein rte ans Ende packt, sondern als allererstes (wann auch sonst?) Register auf den Stack packt.
    Und hier reichen schon die zwei Anweisungen (lea / movem), daß uCos innerhalb der ersten 1/10sec abschmiert.

    Aber ganz sicher ist es nicht so, daß ISRs nicht in C schreibbar sind

    DAS habe ich auch nicht behauptet, aber es gilt halt nicht immer.
    Aber mit zwei Macros im C-Source kann ich gut leben 😃



  • ArneS schrieb:

    das Dumme ist nur: Der Coldfire 5307 hat keine MMU! Das haben m.W. nur einige mit dem 4e Kern.

    Was soll das für ein Prozessor sein? Wenn's keine MMU gibt, dann gibt es auch nur einen Ring und ein Interrupt, der angenommen wurde, sperrt erstmal die Kiste, schmeißt mindestens seinen PC auf den Stack und lädt die Adresse der ISR da hinein.
    Daß dann der Compiler meint, noch Register auf den Stack legen zu müssen, ja blah, aber trotzdem darf kein weiterer Interrupt durchkommen, es sei denn, man fummelt an der Interruptmask herum.
    An Ausnahmen kenne ich da nur NMI, watchdog und ein paar andere, zumeist hardwaregebundene Scherze. Die dürften dann aber falsch behandelt sein.

    ArneS schrieb:

    Und genau DAS hat mich bei uCos ins Verderben gerissen.

    Wie soll das gehen unter Berücksichtigung meiner vorherigen Ausführungen. Kannst Du das erklären?



  • Was soll das für ein Prozessor sein?

    m68k sind Dir bekannt? Coldfire sind im Prinzip die RISC Version davon. Außen CISC, innen RISC. Mir wäre ein PPCja auch lieber, aber als die HW entwickelt wurde, haben nur Dilettanten das Wort gehabt und heute zahlt die Firma die Zeche für vermurkstes Design - erst recht in der Software!

    Aber worauf zielst Du mit Deiner weiteren Ausführung ab? Kann Dir nicht folgen 😕

    aber trotzdem darf kein weiterer Interrupt durchkommen, es sei denn, man fummelt an der Interruptmask herum.

    Au contraire mon general... M68k kennt IPL0 bis IPL7 (InterruptPriorityLevel). Wird durch drei Bit im Statusregister abgebildet. Tritt ein Interrupt auf, wird der IPL der CPU auf den IPL des anliegenden Interrupts gehoben und nur noch höhere priorisierte Interrupts können dann die Ausführung der gerade ablaufenden ISR unterbrechen, wenn man nicht in der ISR den IPL verringert.
    Wenn Du von Ringen sprichst, kommst Du sicher aus der i386+ Welt?

    Wie soll das gehen unter Berücksichtigung meiner vorherigen Ausführungen. Kannst Du das erklären?

    Nee... erklären kann ich Dir das nicht. 🙄
    Aber wenn ich meine ISR mittels __attribute__ ((interrupt_handler) deklariere und dann zuerst vom Compiler Entry-Code erzeugt wird, bevor ich den IPL auf 7 anheben kann, knallt es.
    Habe heute meine ISR für Receive/Transmit auf der RS232 entsprechend angepasst und mehrere 100kB bei 115k2 übertragen. Habe jetzt auch keine vertauschten Zeichen mehr (statt 0123 dann 0213 z.B.) oder Zeichen, die verlorengingen.
    Wenn ich wüßte, wie ich auf PC Seite meine PCMCIA Karte auf 460k8 vom Terminalprg. einstellen kann, würde ich das mal von Coldfire Seite probieren.



  • ArneS schrieb:

    Au contraire mon general... M68k kennt IPL0 bis IPL7 (InterruptPriorityLevel). Wird durch drei Bit im Statusregister abgebildet. Tritt ein Interrupt auf, wird der IPL der CPU auf den IPL des anliegenden Interrupts gehoben und nur noch höhere priorisierte Interrupts können dann die Ausführung der gerade ablaufenden ISR unterbrechen, wenn man nicht in der ISR den IPL verringert.

    Eben nicht!!!! Bei JEDEM µC, der mir in die Finger gefallen ist, werden alle maskierbaren Interrupts durch das automatisch bei Annahme einer Anforderung gesetzte generelle Enable/Disable- Flag kaltgestellt.
    Das evtl. vorhandene Priorizing dient in erster Linie zur Entscheidung über die Annahme zweier zeitgleicher Anforderungen (die höhere kommt zuerst dran) und dann wird geschaut, ob der laufende IPL niedriger ist und dann, aber auch NUR dann, wenn die maskierbaren Interrupts über das Enable- Flag erlaubt sind, wird eine andere ISR unterbrochen.
    Das kommt aber nur zustande, wenn die niedriger priorisierte ISR das Flag im Code auf "enabled" gesetzt hat.
    Wäre es anders, wäre Dein Prozessor ganz großer Mist. 👎

    ArneS schrieb:

    Aber wenn ich meine ISR mittels __attribute__ ((interrupt_handler) deklariere und dann zuerst vom Compiler Entry-Code erzeugt wird, bevor ich den IPL auf 7 anheben kann, knallt es.

    Der IPL ist aber eigentlich nicht zur händischen Manipulation gedacht, da man so leicht die Mechanismen des Prozessors durcheinanderwerfen kann ⚠ .
    Wenn man die ISR initialisiert (also nicht ihr Aufruf), gibt man ihr doch ein Plätzchen in der Vector- Table und den IPL, unter dem sie laufen soll, gleich mit auf den Weg. Warum willst Du da zur Aufrufzeit hinfummeln? 😕



  • Eben nicht!!!! Bei JEDEM µC, der mir in die Finger gefallen ist, werden alle maskierbaren Interrupts durch das automatisch bei Annahme einer Anforderung gesetzte generelle Enable/Disable- Flag kaltgestellt.

    Dann hast Du das Interruptkonzept der m68k nicht verstanden. Es gibt dort nämlich kein generelles Enable/Disable- Flag ⚠

    Wäre es anders, wäre Dein Prozessor ganz großer Mist.

    a) ist das nicht MEIN Prozessor
    b) ist er für unseren Einsatzzweck zwar nicht geeignet, aber trotzdem kein Mist!

    Wenn man die ISR initialisiert (also nicht ihr Aufruf), gibt man ihr doch ein Plätzchen in der Vector- Table und den IPL

    Genau diese Aussage zeigt mir, daß Du das Interruptkonzept des m68k nicht kennst. Aber das wäre jetzt ein anderes Thema und hätte mit dem Ursprungsthema nichts mehr zu tun.

    Warum willst Du da zur Aufrufzeit hinfummeln?

    Wir haben hier Produktionscode, in dem das leider gemacht wird, weil man ein kooperatives OS einsetzt und durch die ISR keine DSR getriggert wird, die die eigentliche Arbeit der ISR übernimmt. Ich gebe zu, daß da meine Vorgänger kein durchdachtes Konzept hatten. Ist leider so. Aber damit mußt DU Dich nicht rumärgern 😉



  • ArneS schrieb:

    Es gibt dort nämlich kein generelles Enable/Disable- Flag ⚠

    Ich hab' nachgesehen, Du hast recht 🙂 und ich unrecht 😞 !

    ArneS schrieb:

    Aber damit mußt DU Dich nicht rumärgern 😉

    Na, gottseidank, wenigstens etwas ... 😃
    Tut mir leid wegen der Nachbohrerei, aber ich hatte wohl wirklich noch nie einen originären 68k auf dem Tisch 🙄



  • ArneS schrieb:

    Wir haben hier Produktionscode, in dem das leider gemacht wird, weil man ein kooperatives OS einsetzt und durch die ISR keine DSR getriggert wird, die die eigentliche Arbeit der ISR übernimmt.

    wirklich ein kooperatives OS? 😉
    meinst du mit DSR sowas wie 'deferred procedure call'?
    sowas lässt sich ja nachrüsten...
    🙂



  • Ich hab' nachgesehen, Du hast recht 🙂 und ich unrecht 😞

    Deswegen hatte ich ja nachgefragt, ob Du aus der i386 Welt kommst. Ich meine mich zu errinnern, daß es da die STI/CLI Anweisungen gab, die alle Interrupts sperrte/freigab. Beim 68HC11 ist das m.W. ähnlich/genauso.
    Beim Coldfire gibt es sog. Autovectorinterrupts, bei denen die CPU selbst den IPL generiert (m.W. nur für interne Peripherie - will mich da aber nicht festlegen ohne Manual) und 'normale' Vektoren, bei denen der Interruptcontroller von außen an den IPL0-2 Pins die Priorität anlegt. Der Index in die Vektortabelle liegt dann an D0-D7 an IIRC.

    Tut mir leid wegen der Nachbohrerei, aber ich hatte wohl wirklich noch nie einen originären 68k auf dem Tisch

    Das kann man hier alles auf sachlicher Ebene klären. Freut mich, daß Du Dir die Mühe gemacht hast nachzusehen. 🙂

    wirklich ein kooperatives OS? 😉
    meinst du mit DSR sowas wie 'deferred procedure call'?
    sowas lässt sich ja nachrüsten...

    Hab ich da was übersehen oder was habe ich bei kooperativem OS nicht verstanden. Das OS lässt sich für Zeitscheiben mit unterschiedlichen Prioritäten konfigurieren, aber auch so flachklopfen, daß der Programmierer mit einer Art yield() Aufrufen (wie in Windoof 3) gezielt den Scheduler aufrufen muß.
    Ja mit DSR meine ich Deferred SubRoutine. Ein Thread der von einer ISR angestoßen wird und die eigentliche Arbeit macht, die nicht zwangsläufig in der ISR ablaufen muß.
    Bei DER Software lässt sich nix mehr nachrüsten - das ist ne Wartungsleiche und gehört in den Giftschrank 👎
    3.3MB in 420 Dateien, der gcc hört bei 100kB Warnings auf weitere zu generieren, ein C/C++ Hybrid, jeder Depp meinte seine eigenen Datentype definieren zu müssen. So findet man wild durch alle Dateien sowohl 'unsigned char', 'BYTE', 'Byte' und 'intu8'. Das macht richtig Spaß 😡
    Den Typen, der mit C++ anfing das Konzept komplett zu zerbröseln, würde ich am liebsten @!%$&*@&%§.... 😡



  • ArneS schrieb:

    Hab ich da was übersehen oder was habe ich bei kooperativem OS nicht verstanden. Das OS lässt sich für Zeitscheiben mit unterschiedlichen Prioritäten konfigurieren...

    diese zeitscheibengesteuerten OS'se werden im allgemeinen als preemptiv bezeichnet. bei einem kooperativen OS muss jede task selber dafür sorgen, das sie nicht zuviel rechenzeit verbrät. hat beides vor- und nachteile.

    ArneS schrieb:

    Ja mit DSR meine ich Deferred SubRoutine. Ein Thread der von einer ISR angestoßen wird und die eigentliche Arbeit macht, die nicht zwangsläufig in der ISR ablaufen muß.

    ja, das verfahren ist bekannt. ich konnte nur das kürzel DSR nicht zuordnen. (ich kenn's als DPC) 😉

    ArneS schrieb:

    Den Typen, der mit C++ anfing das Konzept komplett zu zerbröseln..., würde ich am liebsten @!%$&*@&%§.... 😡

    das wäre genau mein albtraum 😮 eine software (für microcontroller) weiterpflegen, die jemand durch den einsatz von 👎 C++ 👎 verpfuscht hat.
    (ich würde so'n auftrag wahrscheinlich ablehnen, oder alles neu in vernünftigem 👍 C 👍 machen).



  • bzgl. OS: genau so kenne ich es auch. Man hat sich bei uns vor vielen Jahren für CMX entscheiden, das bei uns in kooperativem Betrieb läuft. Man muß in Schleifen selbst mittels eines CMX Aufrufes Rechenzeit abgeben. Sonst kommen nur noch die ISRs zum Zuge. Allerdings hat man mir auch gesagt, daß sich CMX als preemptives OS konfigurieren lässt.

    Das Tolle ist: unser Zeugs compiliert nur mit dem GCC 3.4 - und da nur in -O1. Bei -O0 oder -O2/3 fliegt einem der Compiler um die Ohren. Da wir beim GCC 3.4 meinen zwei Compilerfehler gefunden zu haben, habe ich mich nach neueren Versionen umgeschaut. Leider müssen für den Coldfire wohl spezielle Adaptierungen gemacht werden, da er nur einen abgespeckten m68k Befehlssatz kennt (und der 5307 keinen TAS Befehl 😡 ). Bin dann auf den CodeSourcery GCC gestoßen. Erst 4.1.1, jetzt 4.2.8. Nun ratet mal: unser Zeugs compiliert mit dem 4.x auch nicht. Und woran knallt es? An den C++ Erweiterungen. Zu mir meinte der C++ Fuzzi, daß er wohl Konstrukte benutze, die syntaktisch (!!!) vom 4.x moniert werden, der 3.4 da aber hindrüber wegsieht. Ich liebe es....
    Ich könnte noch seitenweise über die Verfehlungen berichten...

    das wäre genau mein albtraum 😮 eine software (für microcontroller) weiterpflegen, die jemand durch den einsatz von 👎 C++ 👎 verpfuscht hat.
    (ich würde so'n auftrag wahrscheinlich ablehnen, oder alles neu in vernünftigem 👍 C 👍 machen).

    Undertaker! Ich könnt Dich knuddeln 😃
    Ist mir jetzt schon zum zweiten mal bei einem Arbeitgeber passiert. Beim ersten war es allerdings andersrum. Da haben die Jungs streng nach Leerbuch angefangen: für alles erstmal 'ne abstrakte Klasse erstellen, selbst wenn man letztendlich nur eine Instanz benötigte.... und E-Techniker haben dann das Konzept durch mangelhaftes C komplett zerstört. Damals haben wir nach einem halben Jahr die SW in den Giftschrank gestellt und alles neu in C aufgebaut.

    Bei meinem jetzigen AG ziehe ich in meiner Freizeit ein System hoch, um die CPU-Karten und digitalen/analogen Ausgangskarten prüfen zu können. Da uCos m.E. sich schnell anpassen lässt (drei Wochenenden mit BSP für Timer, UARTs und unser externes Bussystem), habe ich mich erstmal hierfür entschieden. Wenn ich da Erfahrung gesammelt habe, werde ich versuchen eCos sammt IP-Stack auf unseren Coldfire zu packen. Aber eins nach dem anderen...


Anmelden zum Antworten