Linker meldet "undefined reference"



  • 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...



  • ArneS schrieb:

    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.

    ja, ich kenne CMX, hab das mal auf infineons (C166'ern) verwendet. ich kann mich dunkel daran erinnern, dass man durch aufruf einer api-funktion preemptives multitasking einschalten musste (per default lief es kooperativ). ich hatte von CMX einen guten eindruck, genau so wie von dem deutschen konkurrenzprodukt 'emBOS' (das hatte ich auf 'nem M16C verwendet).

    ArneS schrieb:

    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.

    ich versuche immer um GCC's einen grossen bogen zu machen, seit mich mal ein GCC für V850 an den rand der verzweiflung getrieben hat 😞
    für embedded programmierung geht nichts über professionelle tools. die sind zwar teuer, aber mit der zeit, die man dabei spart, holt man sich das geld schnell wieder rein.

    ArneS schrieb:

    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....

    hehe, typisch. 😃 C++ programmierer sind in der regel ziemlich realitätsfern, bevorzugen akademisch korrekte lösungen und schön gemachte quelltexte. mit C++ idiomen und ähnlichem dummsinn hat man auf microcontrollern schlechte karten, aber zum glück verirren sich nicht so viele hartnäckige C++ freaks in diese branche (die coden dan doch lieber video games).

    ArneS schrieb:

    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...

    welches nun? eCos oder uCos?



  • und schön gemachte quelltexte

    Das kriegt unser C++ Dödel definitiv nicht hin. Sieht nur zum K*tzen aus...
    Bei meinem Projekt schalte ich alle Warnings an und es kommen nur 5 Warnings momentan am Ende durch - davon zwei, die auf __attribute__ ((norturn)) zurückzuführen sind für die Funktionen, die mit

    while(~0) {
        ...
    }
    

    einen uCos Thread darstellen. Der Rest sind momentan noch "unused variable" etc.
    Und es compiliert/linked/läuft mit allen drei hier vorhandenen Versionen des GCC.
    Man mag ja über den GCC für uC durchaus geteilter Meinung sein. Aber mein Chef ist halt nach eigener Aussage "eine schwäbische Krämerseele" :p
    C'est la vie...

    welches nun? eCos oder uCos?

    uCos (http://www.micrium.com) läuft zwischenzeitlich. Aber deren IP-Stack lässt sich m.E. nicht so problemlos an uCos und den benötigten Treiber (SMC 91C111 - noch so ein Tränenkapitel ) anflanschen.

    Wenn meine Applikation damit läuft, versuche ich eCos (http://ecos.sourceware.org/ zu adaptieren. Vorallem wegen der FreeBSD/OpenBSD IP-Stacks. Bräuchte dann nur noch einen vernünftigen CAN Stack und Treiber für SJA1000.
    Unsere Hardware hat insgesamt folgende Schnittstellen: Ethernet über den 91C111 für die Kommunikation mit einem Steuer-PC, 2x CAN über SJA 1000, 1x RS232 und 1x RS485 (Coldfire intern) plus noch ein proprietäres Bussystem zu Ansteuerung der externen digitalen & analogen Ausgangskarten.
    Wenn ich damit in der Firma auf keine große Gegenliebe stoße, macht sich das alles aber sicher gut in meinem Lebenslauf 😃
    Was hälst Du von uCos, ecos bzw. RTEMS?



  • ArneS schrieb:

    Aber deren IP-Stack lässt sich m.E. nicht so problemlos an uCos und den benötigten...

    also ich benutze als TCP/IP stack entweder OpenTCP
    --> http://sourceforge.net/projects/opentcp/
    oder meinen selbstgebastelten stack 😉
    beide laufen auch ohne RTOS o.ä. und verlangen von der unteren schicht (osi-layer 3 glaub' ich) nur eine sende- und receive-funktion für 802.3/DIX-kompatible pakete. openTCP hat zwar ein paar geringfügige bugs (im ARP z.b.) und wird, glaube ich, auch nicht mehr weiterentwickelt, aber es läuft recht zuverlässig...
    vielleicht interessiert dich auch diese seite: http://www.sics.se/~adam/uip/

    ArneS schrieb:

    ...Treiber (SMC 91C111 - noch so ein Tränenkapitel ) anflanschen.

    das kann doch nicht so schlimm sein. guckst du hier: http://www.google.de/search?q=91C111+filetype%3Ac
    ethernet driver sind eigentlich trivial. mach mal einen für WLAN, das ist spassiger 😉

    ArneS schrieb:

    Bräuchte dann nur noch einen vernünftigen CAN Stack und Treiber für SJA1000.

    nackte CAN frames?
    --> http://svn.gna.org/svn/xenomai/trunk/ksrc/drivers/can/sja1000/
    oder was anderes wie devicenet, CANOpen etc...?

    ArneS schrieb:

    Was hälst Du von uCos, ecos bzw. RTEMS?

    eCos finde ich etwas fett, obwohl man sich ja mit einem grafischen tool zusammenstückeln kann, was man braucht. hat mich etwas an den platform builder für windows-CE erinnert 😉
    die anderen beiden kenne ich nicht (hatte von uCos mal den quelltext, sah gut aus, hab's aber nie ausprobiert)
    zur zeit benutze ich das: --> http://www.tnkernel.com/ auf einem NXP LPC2378 (nachdem ich FreeRTOS evaluiert hatte, welches meiner meinung nach nicht viel taugt)
    🙂



  • OpenTCP kenne ich vom Hörensagen. Hab ihn auch irgendwo auf der Platte rumfliegen.
    Da der Stack, den wir in der Firma benutzen uns Probleme macht (die können natürlich wieder hausgemacht sein 😡 ), wollte ich erstmal den FreeBSD aus ecos benutzen.

    das kann doch nicht so schlimm sein

    Schon mal SMC "Doku" gelesen? Grauenhaft...

    nackte CAN frames?

    Falscher Fehler.... CANOpen natürlich 🙄

    nachdem ich FreeRTOS evaluiert hatte, welches meiner meinung nach nicht viel taugt

    Den Eindruck hatte ich auch.
    uCos sieht gut aus - besonders, da Ports für so ~30 CPUs zur Verfügung stehen und man in Application Notes alles haarklein erklärt bekommt. Der einzige Nachteil is m.E., daß es je Priorität nur einen Thread zulässt.

    ecos und auch RTEMS sind dicke Brocken - für C166 oder 8Bitter damit nicht geeignet. Aber wir haben 4MB Flash und 4MB RAM am Coldfire zur Verfügung 😃
    Deine Links werde ich mal durchforsten. Danke!


Anmelden zum Antworten