Linker meldet "undefined reference"
-
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 DeklarationINTERRUPT(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:
- Codesourcery hat recht - naked gibts beim Coldfire-Port nicht
- gcc erzeugt Entry/Exit Code (Pushen/Poppen von vier Registern), wenn man __attribute__ ((interrupt_handler)) benutzt
- benutzt man keine Attribut und legt auch keine lokalen Variablen an, dann wird kein Entry/Exit Code erzeugt.
- Sollte man lokale Variablen benötigen, müßte man m.E. auf static-Variablen ausweichen
- 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") }
- 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...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ünftigemC
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ünftigemC
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 mitwhile(~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 spassigerArneS 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!